核心要点速览
- 访问控制:public(接口)、private(实现)、protected(继承)
- const 成员:const 成员变量需初始化列表初始化;const 成员函数不可修改成员变量
- static 成员:静态成员变量类共享、类外初始化;静态成员函数无 this 指针、仅访问静态成员
- 构造函数:可重载、非虚函数;含默认 / 带参 / 拷贝 / 移动构造
- 析构函数:不可重载;基类需设为虚函数避免资源泄漏
- 类大小:仅取决于非静态数据成员,遵循内存对齐
一、基本概念
- 类:抽象的数据类型模板,定义对象的属性(数据成员)和行为(成员函数)。
- 对象:类的具体实例,占用实际内存,拥有类定义的属性和行为。
二、核心特性:封装
核心是 “隐藏实现细节,暴露公共接口”,通过访问控制符实现。
| 访问控制符 | 可访问范围 | 作用 |
|---|---|---|
public | 类内、类外、派生类 | 暴露接口,供外部调用 |
private | 仅类内和友元 | 隐藏数据成员和内部实现 |
protected | 类内、友元、派生类(类外不可访问) | 为继承预留访问权限 |
- 封装意义:保障数据安全、提升代码维护性、降低使用复杂度。
三、构造函数:对象的初始化
- 核心特点:函数名与类名相同,无返回值,对象创建时自动调用,可重载,不能为虚函数。
常见类型
1. 默认构造函数
- 定义:无参数,或所有参数都有默认值。
- 编译器行为:未定义任何构造函数时自动生成;定义其他构造函数后需手动定义。
2. 带参构造函数
- 用途:通过参数灵活初始化对象。
3. 拷贝构造函数
- 定义:参数必须为 “同类对象的 const 引用”(避免无限递归)。
- 调用时机:对象初始化、函数按值传参、函数返回值为对象(非引用)。
- 浅拷贝 vs 深拷贝:
- 浅拷贝:仅复制表层数据,指针成员共享内存,可能导致双重释放。
- 深拷贝:为指针成员重新分配内存并复制数据,示例:
class String {
private:
char* str;
public:
String(const String& other) {
str = new char[strlen(other.str) + 1];
strcpy(str, other.str);
}
~String() { delete[] str; }
};
4. 移动构造函数
- 核心:接管原对象动态资源,避免拷贝,提升效率。
- 示例:
class String {
private:
char* str;
public:
String(String&& other) noexcept {
str = other.str;
other.str = nullptr; // 掏空原对象
}
};
String s2 = std::move(s1); // 接管s1资源
初始化列表
- 用途:优先初始化成员变量,推荐使用。
- 必须使用的场景:const 成员、引用成员、无默认构造函数的类成员,示例:
class A {
private:
const int a;
int& b;
public:
A(int x, int& y) : a(x), b(y) {} // 初始化列表
};
四、析构函数:对象的清理
- 特点:函数名
~类名,无参数、无返回值,不可重载,对象生命周期结束时自动调用。 - 必须手动定义的场景:类包含动态分配资源(如 new 的内存)。
- 虚析构函数(基类必备,避免资源泄漏):
class Base {
public:
virtual ~Base() { delete[] data; } // 虚析构
};
class Derived : public Base {
public:
~Derived() { delete[] derivedData; }
};
五、this 指针
- 本质:非静态成员函数中隐式传递的指针,指向当前调用对象(类型
类名* const)。 - 用途:
void setName(string name) { this->name = name; } // 区分成员与参数
Person& setAge(int age) { return *this; } // 链式调用
六、静态成员(属于类)
1. 静态成员变量
- 特点:所有对象共享,存储在全局数据区,类内声明、类外初始化:
class Counter {
public:
static int count; // 类内声明
};
int Counter::count = 0; // 类外初始化
2. 静态成员函数
- 特点:无 this 指针,无需创建对象即可调用,仅能访问静态成员:
static void increment() { count++; } // 仅访问静态成员
Counter::increment(); // 直接调用
七、类的大小计算
- 规则:仅取决于非静态数据成员,遵循内存对齐,与成员函数、静态成员无关。
- 示例:
class Empty {};
sizeof(Empty); // 1字节(占位)
class A { char c; int i; };
sizeof(A); // 8字节(1+3填充+4,对齐系数4)
八、问答
- 构造函数和析构函数的调用顺序?
- 构造:先定义先构造;析构:后构造先析构。
- 拷贝构造函数的参数为什么必须是引用?
- 避免值传递引发的无限递归(形参初始化需再次调用拷贝构造)。
813

被折叠的 条评论
为什么被折叠?



