类的基础

类与对象的定义

核心概念

  • 类(class):C++面向对象(OOP,Object Oriented Programming)的核心概念,是对现实世界事物的抽象描述——包含事物的属性(数据)行为(方法)
    • 语法层面:增加了函数的结构体;
    • 逻辑层面:增加了数据行为的结构体(结构体仅侧重存储属性)。
  • 对象(Object):类类型定义的变量,是类的实例化产物,对应现实世界中的具体事物。
    • 例:Cat tom; 中,tomCat 类的对象。
类与对象的关系示意图(类为模板,对象为模板生成的具体实例)

现实世界抽象示例

现实事物 属性(数据) 行为(方法)
小猫 毛色、体重、性别、年龄 进食、睡觉、卖萌
文件 类型、权限、大小 打开、关闭、读写
进度条 尺寸、百分比、颜色 进度更新、弹窗提示
电视机 尺寸、品牌、音量、频道、稳压器、电路板 开机、关机、切换频道、调节音量

语法格式

class 类名 {
public:  // 成员限定符(后续详细讲解)
    // 成员属性(数据)
    数据类型 属性名1;
    数据类型 属性名2;
    ...
    
    // 成员方法(行为/函数)
    返回值类型 方法名1(参数列表) {
        方法实现;
    }
    返回值类型 方法名2(参数列表) {
        方法实现;
    }
    ...
};

基础示例代码

#include <iostream>
using namespace std;

// 自定义类类型 A
class A {
public:
    // 成员属性
    int x;
    float y;

    // 成员方法
    void showInfo() {
        cout << "x:" << x << endl;
        cout << "y:" << y << endl;
    }
};

// 主函数中使用类
int main(void) {
    A a;  // 定义A类的对象a(类变量 = 对象)
    
    // 访问公有属性并赋值
    a.x = 100;
    a.y = 1.2f;
    
    // 调用公有方法
    a.showInfo();
    return 0;
}

类与结构体(C语言)的区别

对比项 结构体(C语言) 类(C++)
成员类型 仅支持数据属性 支持数据属性 + 成员方法
默认访问权限 公有(public) 私有(private)
核心用途 存储数据集合 抽象事物(属性+行为封装)

唯二关键区别

  1. 类支持成员方法(函数),结构体仅支持数据;
  2. 类默认访问权限为private,结构体默认public。

类方法

核心概念

类方法是类中的函数接口,用于描述对象的行为属性,必须通过对象(或类,静态方法除外)调用。

定义与调用示例

#include <iostream>
using namespace std;

class Kitty {
public:
    // 成员方法(行为)
    void eat() { cout << "小猫进食" << endl; }
    void sleep() { cout << "小猫睡觉" << endl; }
    void actCute() { cout << "小猫卖萌" << endl; }
};

int main(void) {
    Kitty myCat;
    
    // 正确:通过对象调用非静态方法
    myCat.eat();    // 输出:小猫进食
    myCat.sleep();  // 输出:小猫睡觉
    myCat.actCute();// 输出:小猫卖萌
    
    // 错误:非静态方法不能直接通过类调用(需对象实例)
    // Kitty::eat(); 
    return 0;
}

类方法设计原则

  1. 仅将与对象核心行为相关的逻辑封装为类方法(如小猫的“进食”,而非“被人类抱起”);
  2. 需考虑继承场景:通用行为(如动物的“呼吸”)在父类实现,特殊行为(如鸟的“飞行”)在子类实现;
  3. 方法需提供清晰接口,内部逻辑对外部透明(封装特性)。
类方法调用流程示意图(对象 → 调用方法 → 执行行为)

类成员权限限定符

三种权限定义与访问范围

类通过权限限定符控制成员的访问范围,核心目的是封装保护(隐藏内部实现,暴露安全接口)。

限定符 访问范围 核心特点
public(公有) 类内、类外、子类均可访问 对外暴露的接口(方法/属性)
protected(保护) 类内、子类可访问,类外不可访问 继承场景下的中间权限
private(私有) 仅类内可访问,类外、子类均不可访问 需保护的核心属性/内部方法

注意:类中未显式标注限定符的成员,默认是private(结构体默认public)。

语法示例代码

#include <iostream>
using namespace std;

class A {
    int w; // 默认:私有成员(private)

private:
    int x; // 私有成员

protected:
    int y; // 保护成员

public:
    int z; // 公有成员

    // 类内方法可访问所有权限的成员
    void f() {
        w = 10;  // 合法:类内访问私有成员
        x = 100; // 合法:类内访问私有成员
        y = 200; // 合法:类内访问保护成员
        z = 300; // 合法:类内访问公有成员
    }
};

int main(void) {
    A a;

    // 错误:类外无法访问私有/保护成员
    // a.w = 20;
    // a.x = 200;
    // a.y = 300;

    // 正确:类外可访问公有成员
    a.z = 400;
    a.f(); // 正确:调用公有方法(方法内部访问私有/保护成员)
    return 0;
}

权限设计基本原则

  • 成员属性:优先设为private(禁止外部直接修改,避免逻辑错误);
    • 若需修改/获取属性,通过公有方法封装(如setAge(int age)进行边界检测);
  • 成员方法:优先设为public(对外提供行为接口);
    • 内部辅助逻辑设为private(如计算辅助函数);
    • 继承场景下需子类复用的方法设为protected
三种权限访问范围对比图(用三个圈层表示类内、子类、类外的访问权限)

构造函数(特殊成员方法)

核心概念

  • 用途:对象创建时自动调用,用于初始化成员属性(避免属性为随机值);
  • 特点:无返回值(不可写void),函数名与类名完全一致;
  • 分类:无参构造、带参构造、默认参数构造。

语法示例代码

#include <iostream>
#include <string>
using namespace std;

class Cat {
private:
    // 私有成员属性(遵循权限设计原则)
    string Name;
    string Color;
    char Sex;
    int Age;

public:
    // 1. 无参构造函数(默认构造)
    Cat() {
        cout << "无参数的构造版本.." << endl;
        Name = "Tom";
        Color = "Red";
        Sex = 'M';
        Age = 1;
    }

    // 2. 带参构造函数(含默认参数)
    Cat(const string name, const string color, const int age = 1, const char sex = 'N') {
        cout << "带参数的构造版本.." << endl;
        Name = name;
        this->Color = color; // this指针:指向当前对象,区分成员变量与参数名
        this->Sex = sex;
        this->Age = age;
    }

    // 公有方法:访问私有属性
    void showInfo() {
        cout << "Name: " << Name << endl;
        cout << "Color: " << Color << endl;
        cout << "Sex: " << Sex << endl;
        cout << "Age: " << Age << endl;
        cout << "--------------------" << endl;
    }

    // 公有方法:修改私有属性(带边界检测)
    void setAge(int age) {
        if (age >= 100) age = 99; // 防止不合理值
        Age = age;
    }
};

// 主函数测试
int main(int argc, char const *argv[]) {
    Cat tom; // 调用无参构造
    tom.showInfo();

    Cat jarry("Jarry", "黄色"); // 调用带参构造(默认age=1,sex='N')
    jarry.setAge(199); // 调用公有方法修改私有属性(最终age=99)
    jarry.showInfo();

    Cat jarryBrother("JarryBrother", "灰色", 3, 'M'); // 显式传所有参数
    jarryBrother.showInfo();

    // 拷贝构造(预习内容):用已有对象初始化新对象
    Cat j1 = jarry;
    j1.showInfo();

    return 0;
}

关键注意事项

  1. 若未自定义构造函数,编译器会生成默认无参构造(空实现);
  2. 若自定义了带参构造,编译器不再生成默认无参构造(需手动显式定义);
  3. 默认参数需放在参数列表末尾(如const int age = 1, const char sex = 'N');
  4. this指针:隐含在非静态成员方法中,指向当前对象,用于区分成员变量与参数名(如this->Color = color)。

拓展(补充核心知识点)

this指针详解

  • 本质:非静态成员方法的隐含参数(编译器自动添加),类型为类名* const(指针本身不可修改);
  • 用途
    1. 区分成员变量与函数参数名(如this->Age = age);
    2. 在方法中返回当前对象(return *this,支持链式调用);
  • 注意:静态方法中无this指针(静态方法不依赖对象实例)。

链式调用示例

class Calculator {
private:
    int result;
public:
    Calculator() { result = 0; }
    Calculator& add(int num) { // 返回对象引用
        result += num;
        return *this; // 返回当前对象
    }
    Calculator& sub(int num) {
        result -= num;
        return *this;
    }
    void showResult() { cout << "结果:" << result << endl; }
};

// 调用:链式调用多个方法
Calculator cal;
cal.add(10).sub(3).add(5); // 结果 = 0+10-3+5=12
cal.showResult();

成员变量命名规范(行业通用)

  • 私有成员变量前加下划线(如_name_age),避免与参数名冲突(减少this指针使用);
    class Cat {
    private:
        string _name; // 私有成员加下划线
        int _age;
    public:
        void setName(string name) { _name = name; } // 无需this指针
    };
    
  • 类名首字母大写(如CatMonster),方法名首字母小写(如showInfosetAge)。

静态成员(static)基础

  • 静态成员变量
    1. 所有对象共享同一数据(如“人类的共同属性:物种=人类”);
    2. 需在类外初始化(数据类型 类名::变量名 = 初始值);
    3. 可通过类名直接访问(类名::变量名),无需对象实例。
  • 静态成员方法
    1. this指针,只能访问静态成员变量/方法;
    2. 可通过类名或对象调用。

示例代码

class Human {
public:
    static string species; // 静态成员变量(所有人类共享)
    static void showSpecies() { // 静态成员方法
        cout << "物种:" << species << endl;
    }
};

// 类外初始化静态成员变量
string Human::species = "智人";

int main() {
    // 无需对象,直接通过类名访问
    Human::showSpecies(); // 输出:物种:智人
    Human::species = "人类";
    
    Human p1, p2;
    p1.showSpecies(); // 输出:物种:人类(共享数据)
    return 0;
}

析构函数基础

  • 用途:对象销毁时(生命周期结束)自动调用,用于释放资源(如动态内存、文件句柄);
  • 特点:无返回值,无参数,函数名前加~,与类名一致;
  • 示例:
    class File {
    private:
        FILE* _file;
    public:
        // 构造函数:打开文件
        File(const char* filename) {
            _file = fopen(filename, "r");
        }
        // 析构函数:关闭文件(释放资源)
        ~File() {
            if (_file != NULL) fclose(_file);
            cout << "文件已关闭" << endl;
        }
    };
    

posted @ 2025-12-17 08:27  Jaklin  阅读(33)  评论(0)    收藏  举报