C++面向对象真没那么难:类与对象(上篇)-优快云博客文章浏览阅读571次,点赞9次,收藏10次。刚学C++的来看!!!!面向对象真没那么难https://blog.youkuaiyun.com/wz_290793/article/details/149486147?spm=1001.2014.3001.5502C++类和对象(下):从初始化列表到编译器优化-优快云博客刚学c++的来看!!!
https://blog.youkuaiyun.com/wz_290793/article/details/149523760?spm=1001.2014.3001.5502
目录
C++类和对象(中篇):深入理解默认成员函数
类就像一辆新车,默认成员函数是它的“出厂设置”
掌握构造、析构和拷贝构造,让你的对象从“能用”变成“好用”!
一、默认成员函数:类自带的“出厂配置”
每个类都有6个自动生成的默认成员函数(前4个最重要):
class YourClass {
// 编译器自动生成以下6个函数:
YourClass(); // 1. 构造函数
~YourClass(); // 2. 析构函数
YourClass(const YourClass&); // 3. 拷贝构造
YourClass& operator=(const YourClass&); // 4. 赋值重载
// ...(后两个取地址重载较少用)
};
核心原则:
- 不写时,编译器自动生成
- 自动生成的版本是否满足需求?
- 不满足时,如何自己实现?
二、构造函数:对象的“出生证明”
2.1 构造函数的作用
替代C语言中的Init()
函数,自动完成初始化:
class Date {
public:
// 构造函数(类名相同)
Date(int year = 1, int month = 1, int day = 1) {
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
// 创建对象自动调用构造
Date today(2024, 7, 21); // 带参构造
Date defaultDay; // 默认构造(无参)
2.2 构造函数的秘密
- 必须与类同名
- 没有返回值(连void都不写)
- 对象创建时自动调用
- 可以重载(不同参数版本)
- 默认构造三选一:
- 无参构造
Date()
- 全缺省构造
Date(int y=1, int m=1, int d=1)
- 编译器自动生成的构造
- 无参构造
⚠️ 易错点:
Date d3();
会被当成函数声明!
三、析构函数:对象的“临终遗言”
3.1 何时需要析构
当类管理资源(内存、文件句柄等)时必须手动实现:
class Stack {
public:
Stack(int n = 4) {
_a = (int*)malloc(sizeof(int) * n); // 申请资源
}
~Stack() { // 析构函数(~类名)
free(_a); // 释放资源
_a = nullptr;
cout << "资源已释放!" << endl;
}
private:
int* _a;
int _capacity;
int _top;
};
3.2 析构函数的特点
- 名称是
~类名
- 无参数无返回值
- 对象销毁时自动调用
- 多个对象按创建顺序反向析构(后进先出)
💡 像
Date
这样没有资源的类,不需要写析构!
四、拷贝构造:对象的“克隆技术”
4.1 深浅拷贝之争
浅拷贝:只复制指针地址(危险!)
深拷贝:复制指针指向的内容(安全)
// 正确实现深拷贝
Stack(const Stack& st) {
_a = (int*)malloc(sizeof(int) * st._capacity);
memcpy(_a, st._a, sizeof(int) * st._top);
_top = st._top;
_capacity = st._capacity;
}
4.2 拷贝构造规则
- 必须是引用传参:
Date(const Date& d)
- 参数通常加
const
保护 - 自定义类型传值会触发拷贝构造
✨ 何时需要深拷贝?类中有指针指向动态资源时!
五、赋值重载:对象的“身份复制”
5.1 运算符重载基础
让自定义类型支持 +
, -
, ==
等操作:
class Date {
public:
// 重载==运算符
bool operator==(const Date& d) const {
return _year == d._year
&& _month == d._month
&& _day == d._day;
}
};
5.2 赋值运算符重载
Date& operator=(const Date& d) {
if(this != &d) { // 防止自我赋值
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this; // 支持连续赋值 d1 = d2 = d3;
}
5.3 赋值 vs 拷贝构造
场景 | 使用拷贝构造 | 使用赋值重载 |
---|---|---|
对象创建时 | Date d2 = d1; | ❌ 不适用 |
对象已存在 | ❌ 不适用 | d2 = d1; |
六、实战:日期类综合实现
class Date {
public:
// 构造
Date(int y = 1900, int m = 1, int d = 1);
// 析构(无资源,不需要实现)
// 拷贝构造
Date(const Date& d) : _year(d._year), _month(d._month), _day(d._day) {}
// 赋值重载
Date& operator=(const Date& d) {
if(this != &d) {
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
// 比较运算符
bool operator<(const Date& d) const { /* 实现 */ }
bool operator==(const Date& d) const { /* 实现 */ }
// 日期计算
Date operator+(int days) const;
Date& operator+=(int days);
private:
int _year;
int _month;
int _day;
};
未完持续...(关注我,宝子,C++学习带你飞起来!!!)
现在只需掌握:构造负责出生,析构负责善后,拷贝实现克隆
动手实现一个Student
类(包含姓名/学号/拷贝构造),遇到问题随时回看~🚀