1. C++类与对象深度解析
作为一名有着十年C++开发经验的老程序员,我深知类和对象是C++面向对象编程的核心概念。今天,我将从实际工程角度,带大家深入理解C++中类和对象的方方面面,包括那些教科书上不会告诉你的实战技巧和陷阱。
1.1 类的定义与封装
1.1.1 类的基本结构
在C++中,类是用户自定义的数据类型,它封装了数据(成员变量)和操作这些数据的方法(成员函数)。下面是一个典型的类定义示例:
cpp复制class Stack {
public:
// 成员函数
void Init(int n = 4) {
array = (int*)malloc(sizeof(int) * n);
if (nullptr == array) {
perror("malloc申请空间失败");
return;
}
capacity = n;
top = 0;
}
private:
// 成员变量
int* array;
size_t capacity;
size_t top;
}; // 注意这个分号不能省略
关键点解析:
class是定义类的关键字,后跟类名(这里是Stack)- 类体用
{}包围,包含成员变量和成员函数 - 类定义结束时必须加分号
- 成员变量通常加前缀或后缀标识(如
_或m),这是行业惯例而非强制要求
工程实践建议:
- 对于资源管理类(如这里的
Stack),建议使用RAII(Resource Acquisition Is Initialization)模式,在构造函数中分配资源,析构函数中释放资源,而不是单独提供Init和Destroy方法。
1.1.2 访问控制与封装
C++通过访问限定符实现封装:
cpp复制class Date {
public: // 公有成员,类外可直接访问
void Print() { /*...*/ }
protected: // 保护成员,仅类内和派生类可访问
int GetDay() { return _day; }
private: // 私有成员,仅类内可访问
int _year;
int _month;
int _day;
};
访问规则:
public:类外可直接访问protected:仅类内和派生类可访问private:仅类内可访问(默认)
重要区别:
class默认访问权限是privatestruct默认访问权限是public(为了兼容C)
设计原则:
- 成员变量通常设为
private或protected - 需要对外提供的接口设为
public - 避免滥用
public成员,这会破坏封装性
1.2 对象实例化与内存布局
1.2.1 实例化过程
cpp复制Date d1; // 调用默认构造函数
Date d2(2023,1,1);// 调用带参构造函数
Date d3 = d1; // 调用拷贝构造函数
内存分配细节:
- 类定义时不会分配内存(只是声明)
- 实例化对象时才分配内存
- 每个对象有独立的数据成员存储空间
- 成员函数代码共享(存储在代码段)
1.2.2 对象大小计算
对象大小由成员变量决定,遵循内存对齐规则:
- 第一个成员在偏移量0处
- 其他成员对齐到
min(成员大小, 默认对齐数)的整数倍地址 - 结构体总大小为最大对齐数的整数倍
- VS默认对齐数为8
示例分析:
cpp复制class A {
char c; // 1字节
int i; // 4字节,对齐到4的倍数
double d; // 8字节,对齐到8的倍数
};
// sizeof(A) = 16 (1 + 3填充 + 4 + 8)
特殊案例:
cpp复制class Empty {};
// sizeof(Empty) = 1 (空类也需要占位)
1.3 this指针揭秘
每个成员函数都隐含一个this指针参数,指向调用对象:
cpp复制void Date::Print() {
cout << _year; // 实际是 cout << this->_year;
}
编译器转换示例:
cpp复制// 源
