目录
[一、类的 6 个默认成员函数(总览)](#一、类的 6 个默认成员函数(总览))
[1.1 通俗概念](#1.1 通俗概念)
[1.2 6 个默认成员函数功能表](#1.2 6 个默认成员函数功能表)
[1.3 注意点](#1.3 注意点)
[2.1 通俗概念](#2.1 通俗概念)
[2.2 关键注意点](#2.2 关键注意点)
[3.1 通俗概念](#3.1 通俗概念)
[3.2 关键注意点](#3.2 关键注意点)
[4.1 通俗概念](#4.1 通俗概念)
[4.2 关键注意点](#4.2 关键注意点)
[5.1 通俗概念](#5.1 通俗概念)
[5.2 前置 ++ 和后置 ++ 重载(日期类实战)](#5.2 前置 ++ 和后置 ++ 重载(日期类实战))
[5.3 关键注意点](#5.3 关键注意点)
[六、const 成员函数](#六、const 成员函数)
[6.1 通俗概念](#6.1 通俗概念)
[6.2 关键注意点](#6.2 关键注意点)
[七、取地址及 const 取地址重载](#七、取地址及 const 取地址重载)
[7.1 通俗概念](#7.1 通俗概念)
[7.2 关键注意点](#7.2 关键注意点)
[8.1 核心功能](#8.1 核心功能)
[8.2 关键注意点](#8.2 关键注意点)
一、类的 6 个默认成员函数(总览)
1.1 通俗概念
空类并不是真的 "空",编译器会自动生成 6 个默认成员函数 ------ 它们是对象 "出生、复制、赋值、销毁" 的默认行为,用户没显式写时,编译器自动补全。
1.2 6 个默认成员函数功能表
|-------------|---------------|---------------------------|
| 函数类型 | 核心功能 | 调用时机 |
| 构造函数 | 初始化对象 | 对象创建时(自动调用) |
| 析构函数 | 清理对象资源 | 对象销毁时(自动调用) |
| 拷贝构造函数 | 用已有对象创建新对象 | 新对象基于旧对象初始化(如Date d2(d1)) |
| 赋值运算符重载 | 把一个对象赋值给另一个对象 | 已有对象间赋值(如d1 = d2) |
| 取地址重载 | 获取对象地址 | 调用&对象时(默认生成即可) |
| const 取地址重载 | 获取 const 对象地址 | 调用&const对象时(默认生成即可) |
1.3 注意点
- 仅当用户未显式实现时,编译器才生成默认版本;
- 默认版本的核心逻辑:对内置类型(int/char 等)"浅拷贝 / 不初始化",对自定义类型(class/struct)调用其对应默认成员函数;
- 涉及资源申请(如 malloc/new)的类,必须显式实现构造、析构、拷贝构造、赋值重载,否则会内存泄漏或崩溃。
二、构造函数
2.1 通俗概念
对象创建时自动调用的函数,核心任务是初始化对象 (不是开空间创建对象),就像婴儿出生时自动登记信息,不用手动操作。
cpp
#include <iostream>
using namespace std;
class Date {
public:
// 1. 无参构造函数(默认构造函数之一)
Date() {
_year = 1900;
_month = 1;
_day = 1;
}
// 2. 带参构造函数
Date(int year, int month, int day) {
_year = year;
_month = month;
_day = day;
}
// 3. 全缺省构造函数(默认构造函数之一)
// Date(int year = 1900, int month = 1, int day = 1) {
// _year = year;
// _month = month;
// _day = day;
// }
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
// C++11特性:内置类型声明时可给默认值
int _year = 0;
int _month = 0;
int _day = 0;
};
int main() {
// 调用无参构造函数(正确)
Date d1;
d1.Print(); // 输出:1900-1-1
// 调用带参构造函数(正确)
Date d2(2024, 5, 22);
d2.Print(); // 输出:2024-5-22
// 错误示例:这是函数声明(返回Date类型,无参),不是对象创建
// Date d3(); // 编译警告:未调用原型函数(误当变量定义)
return 0;
}
cpp
1900-1-1
2024-5-22
2.2 关键注意点
- 默认构造函数的三种形式 :无参构造、全缺省构造、编译器自动生成的构造函数,且默认构造函数只能有一个(注释掉无参构造才能用全缺省,否则编译报错);
- 编译器生成的默认构造函数:
- 对内置类型(int/char 等):C++98 不初始化(随机值),C++11 支持声明时给默认值(如
int _year = 0); - 对自定义类型(如 Time 类):会调用其默认构造函数;
- 对内置类型(int/char 等):C++98 不初始化(随机值),C++11 支持声明时给默认值(如
- 构造函数无返回值 、函数名与类名相同 、支持重载;
- 若用户显式实现任何构造函数(哪怕是带参的),编译器不再生成默认无参构造函数。
面试小提示
常考:"什么是默认构造函数?"------ 答:无参构造、全缺省构造、编译器默认生成的构造函数,三者只能存在一个。
三、析构函数
3.1 通俗概念
对象生命周期结束时自动调用的函数,核心任务是清理资源(如 malloc 的内存、打开的文件),就像人去世前清理个人物品,对象销毁前释放申请的资源。
cpp
#include <iostream>
#include <cstdlib>
using namespace std;
typedef int DataType;
class Stack {
public:
// 构造函数:申请资源
Stack(size_t capacity = 3) {
_array = (DataType*)malloc(sizeof(DataType) * capacity);
if (nullptr == _array) {
perror("malloc申请空间失败");
return;
}
_capacity = capacity;
_size = 0;
cout << "Stack():申请内存成功" << endl;
}
// 析构函数:清理资源(必须显式实现,否则内存泄漏)
~Stack() {
if (_array) {
free(_array);
_array = nullptr; // 避免野指针
_capacity = 0;
_size = 0;
cout << "~Stack():释放内存成功" << endl;
}
}
void Push(DataType data) {
// 简化版:未实现扩容
if (_size < _capacity) {
_array[_size++] = data;
}
}
private:
DataType* _array; // 动态申请的内存(需清理)
size_t _capacity;
size_t _size;
};
void TestStack() {
Stack s;
s.Push(1);
s.Push(2);
// 函数结束时,s生命周期结束,自动调用析构函数
}
int main() {
TestStack();
return 0;
}
cpp
Stack():申请内存成功
~Stack():释放内存成功
3.2 关键注意点
- 析构函数无参数、无返回值 、函数名是类名前加~ 、不能重载(一个类只有一个析构函数);
- 编译器生成的默认析构函数:
- 对内置类型:不做任何处理(如 int/char,无需清理);
- 对自定义类型:调用其析构函数(如 Date 类中的 Time 成员,会自动调用~Time ());
- 若类中无资源申请(如 Date 类),可不用显式实现析构函数;若有资源申请(如 Stack 类的 malloc),必须显式实现,否则内存泄漏。
面试小提示
常考:"析构函数的作用是什么?什么时候需要显式实现?"------ 答:清理对象资源;类中涉及动态内存申请、文件打开等资源时,必须显式实现。
四、拷贝构造函数
4.1 通俗概念
用一个已存在的对象创建新对象时自动调用的函数,核心任务是复制对象的所有成员,就像用双胞胎哥哥的信息创建弟弟的身份档案。
cpp
#include <iostream>
using namespace std;
class Date {
public:
// 构造函数
Date(int year = 1900, int month = 1, int day = 1) {
_year = year;
_month = month;
_day = day;
cout << "Date(int, int, int):" << this << endl;
}
// 拷贝构造函数:参数必须是const引用(避免无穷递归)
Date(const Date& d) {
_year = d._year;
_month = d._month;
_day = d._day;
cout << "Date(const Date&):" << this << endl;
}
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
// 错误示例:拷贝构造函数参数为传值(编译报错,无穷递归)
// class Date {
// public:
// Date(Date d) { // 错误:传值会触发拷贝构造,无限循环
// _year = d._year;
// }
// };
// 拷贝构造调用场景1:用已有对象创建新对象
void Test1() {
Date d1(2024, 5, 22);
Date d2(d1); // 调用拷贝构造
d2.Print(); // 输出:2024-5-22
}
// 拷贝构造调用场景2:函数参数为类类型对象
void Test2(Date d) { // 传值时调用拷贝构造
d.Print();
}
// 拷贝构造调用场景3:函数返回值为类类型对象
Date Test3() {
Date d(2024, 5, 23);
return d; // 返回时调用拷贝构造(编译器可能优化)
}
int main() {
Test1();
cout << "----------------" << endl;
Date d4(2024, 5, 24);
Test2(d4);
cout << "----------------" << endl;
Date d5 = Test3();
return 0;
}
cpp
Date(int, int, int):0x7ffee3b558a0
Date(const Date&):0x7ffee3b55890
2024-5-22
----------------
Date(int, int, int):0x7ffee3b55880
Date(const Date&):0x7ffee3b55850
2024-5-24
----------------
Date(int, int, int):0x7ffee3b55840
Date(const Date&):0x7ffee3b55870
4.2 关键注意点
- 拷贝构造函数是构造函数的重载 ,参数必须是
const 类名&:- 用引用是为了避免传值触发拷贝构造,导致无穷递归;
- 用 const 是为了保护原对象,避免被修改;
- 编译器生成的默认拷贝构造函数:
- 对内置类型:按字节浅拷贝(值拷贝);
- 对自定义类型:调用其拷贝构造函数;
- 浅拷贝的问题:若类中有资源申请(如 Stack 类),浅拷贝会导致两个对象共用同一块内存,析构时重复释放(崩溃),需显式实现深拷贝;
- 三大调用场景:用旧对象创建新对象、函数参数为类类型(传值)、函数返回值为类类型(传值)。
面试小提示
常考:"拷贝构造函数为什么参数必须是引用?"------ 答:若为传值,会触发拷贝构造函数本身,导致无限递归调用,编译报错。
五、赋值运算符重载
5.1 通俗概念
已有对象间赋值时调用的函数(如d1 = d2),核心任务是把一个对象的成员赋值给另一个对象,区别于拷贝构造(拷贝构造是 "创建新对象",赋值是 "已有对象赋值")。
cpp
#include <iostream>
using namespace std;
class Date {
public:
// 构造函数
Date(int year = 1900, int month = 1, int day = 1) {
_year = year;
_month = month;
_day = day;
}
// 拷贝构造函数
Date(const Date& d) {
_year = d._year;
_month = d._month;
_day = d._day;
cout << "拷贝构造" << endl;
}
// 赋值运算符重载(正确格式)
Date& operator=(const Date& d) {
// 1. 检测自赋值(避免自己给自己赋值,浪费资源)
if (this != &d) {
_year = d._year;
_month = d._month;
_day = d._day;
}
// 2. 返回*this(支持连续赋值,如d1 = d2 = d3)
return *this;
}
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
// 错误示例:赋值运算符重载成全局函数(编译报错)
// Date& operator=(Date& left, const Date& right) {
// if (&left != &right) {
// left._year = right._year;
// }
// return left;
// }
int main() {
Date d1(2024, 5, 22), d2(2024, 5, 23), d3;
// 连续赋值(支持,因为返回Date&)
d3 = d2 = d1;
d3.Print(); // 输出:2024-5-22
// 赋值 vs 拷贝构造
Date d4 = d1; // 拷贝构造(创建d4时初始化)
Date d5;
d5 = d1; // 赋值运算符重载(d5已存在)
return 0;
}
cpp
拷贝构造
2024-5-22
5.2 前置 ++ 和后置 ++ 重载(日期类实战)
通俗概念
- 前置 ++:先自增,再返回自增后的对象(如
++d,返回 d+1 后的值); - 后置 ++:先返回当前对象,再自增(如
d++,返回 d 原来的值,之后 d+1)。
cpp
#include <iostream>
using namespace std;
class Date {
public:
Date(int year = 1900, int month = 1, int day = 1) {
_year = year;
_month = month;
_day = day;
}
// 前置++:返回引用(对象未销毁,直接修改)
Date& operator++() {
_day += 1;
// 这里简化处理,未考虑月份/年份进位(完整逻辑见日期类实现)
return *this;
}
// 后置++:返回值(需保存旧值,临时对象不能返回引用)
// 加int参数是占位符,编译器自动传递,区分前置/后置
Date operator++(int) {
Date temp(*this); // 保存当前对象(旧值)
_day += 1; // 自增
// 简化处理,未考虑进位
return temp; // 返回旧值
}
void Print() {
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d(2024, 5, 22);
// 后置++:先使用,后自增
Date d1 = d++;
cout << "d1(d++后):";
d1.Print(); // 输出:2024-5-22(旧值)
cout << "d(d++后):";
d.Print(); // 输出:2024-5-23(自增后)
// 前置++:先自增,后使用
Date d2 = ++d;
cout << "d2(++d后):";
d2.Print(); // 输出:2024-5-24(自增后)
cout << "d(++d后):";
d.Print(); // 输出:2024-5-24(自增后)
return 0;
}
cpp
d1(d++后):2024-5-22
d(d++后):2024-5-23
d2(++d后):2024-5-24
d(++d后):2024-5-24
关键注意点
- 前置 ++:
- 无占位参数,返回
Date&(当前对象未销毁,直接返回引用,提高效率); - 先修改对象,再返回修改后的对象;
- 无占位参数,返回
- 后置 ++:
- 必须加
int占位参数(无实际意义,仅用于编译器区分); - 返回
Date(值返回),因为需要保存旧值(临时对象),不能返回引用;
- 必须加
- 完整实现需处理日期进位(如 5 月 31 日 ++ 后是 6 月 1 日),后续日期类会补充。
面试小提示
常考:"前置 ++ 和后置 ++ 重载的区别?"------ 答:1. 参数:后置多一个 int 占位符;2. 返回值:前置返回引用,后置返回值;3. 逻辑:前置先自增后返回,后置先返回后自增;4. 效率:前置更高(无临时对象拷贝)。
5.3 关键注意点
- 赋值运算符重载的必须格式 :
- 参数类型:
const 类名&(提高传参效率,保护原对象); - 返回值类型:
类名&(支持连续赋值,提高返回效率); - 检测自赋值(
this != &d); - 返回
*this;
- 参数类型:
- 赋值运算符只能重载为类的成员函数:不能重载成全局函数,否则与编译器生成的默认版本冲突(编译报错);
- 编译器生成的默认赋值运算符重载:
- 对内置类型:浅拷贝(值拷贝);
- 对自定义类型:调用其赋值运算符重载;
- 与拷贝构造的区别:拷贝构造是 "创建新对象时复制",赋值是 "已有对象间复制"。
面试小提示
常考:"哪些运算符不能重载?"------ 答:.*、::、sizeof、?:、.,共 5 个。
六、const 成员函数
6.1 通俗概念
用 const 修饰的成员函数,核心是修饰隐含的 this 指针 (const 类名* const this),表明该函数不能修改对象的任何成员变量,就像给对象上了 "只读锁"。
cpp
#include <iostream>
using namespace std;
class Date {
public:
Date(int year = 1900, int month = 1, int day = 1) {
_year = year;
_month = month;
_day = day;
}
// 非const成员函数:可以修改成员变量
void Print() {
cout << "Print()" << endl;
cout << _year << "-" << _month << "-" << _day << endl;
}
// const成员函数:不能修改成员变量(this指针被const修饰)
void Print() const {
cout << "Print() const" << endl;
cout << _year << "-" << _month << "-" << _day << endl;
// _year = 2025; // 错误:const成员函数不能修改成员变量
}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d1(2024, 5, 22); // 非const对象
const Date d2(2024, 5, 23); // const对象
d1.Print(); // 调用非const成员函数(输出Print())
d2.Print(); // 调用const成员函数(输出Print() const)
// d2.Print(); // 正确:const对象只能调用const成员函数
// d1.Print(); // 正确:非const对象可以调用const成员函数
return 0;
}
cpp
Print()
2024-5-22
Print() const
2024-5-23
6.2 关键注意点
- const 对象只能调用 const 成员函数;
- 非 const 对象可以调用 const 和非 const 成员函数(优先调用非 const 版本);
- const 成员函数不能调用非 const 成员函数(非 const 函数可能修改成员);
- 非 const 成员函数可以调用 const 成员函数。
面试小提示
这是高频考点!直接考 "const 对象能否调用非 const 成员函数?"------ 答:不能,const 对象的 this 指针是const 类名*,非 const 成员函数的 this 指针是类名*,类型不兼容。
七、取地址及 const 取地址重载
7.1 通俗概念
用于获取对象的地址,编译器会自动生成默认版本,一般无需用户显式实现,只有特殊需求(如隐藏真实地址)时才需要自定义。
cpp
#include <iostream>
using namespace std;
class Date {
public:
Date(int year = 1900, int month = 1, int day = 1) {
_year = year;
_month = month;
_day = day;
}
// 取地址重载(默认生成的版本,无需显式写)
Date* operator&() {
return this; // 返回当前对象地址
}
// const取地址重载(默认生成的版本)
const Date* operator&() const {
return this; // 返回const对象地址
}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d1(2024, 5, 22);
const Date d2(2024, 5, 23);
cout << &d1 << endl; // 调用Date* operator&(),输出d1地址
cout << &d2 << endl; // 调用const Date* operator&() const,输出d2地址
return 0;
}
cpp
0x7ffee3b558a0
0x7ffee3b55890
7.2 关键注意点
- 两个重载函数的区别:参数隐含的 this 指针,一个是
Date* const,一个是const Date* const; - 默认生成的版本已能满足需求,仅当需要 "隐藏真实地址"(如返回 nullptr 或固定地址)时,才显式实现;
- 不能重载成全局函数,必须是类的成员函数。
八、日期类完整实现(全功能实战)
8.1 核心功能
包含构造、拷贝构造、赋值重载、日期加减、运算符重载(+、-、+=、-=、++、--、比较运算符)、日期差计算等全功能,解决进位、闰年判断等核心问题。
cpp
#include <iostream>
#include <assert.h>
using namespace std;
class Date {
public:
// 1. 全缺省构造函数
Date(int year = 1900, int month = 1, int day = 1) {
// 校验日期合法性
if (year < 0 || month < 1 || month > 12 || day < 1 || day > GetMonthDay(year, month)) {
cout << "非法日期!" << endl;
assert(false);
}
_year = year;
_month = month;
_day = day;
}
// 2. 拷贝构造函数
Date(const Date& d) {
_year = d._year;
_month = d._month;
_day = d._day;
}
// 3. 赋值运算符重载
Date& operator=(const Date& d) {
if (this != &d) {
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
// 4. 析构函数(无资源申请,默认即可,显式写出为了完整)
~Date() {}
// 5. 获取某年某月的天数(静态成员函数,无需对象即可调用)
static int GetMonthDay(int year, int month) {
assert(month >= 1 && month <= 12);
// 平年月份天数表
static int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// 闰年2月29天
if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))) {
return 29;
}
return days[month];
}
// 6. 日期+=天数(修改当前对象,返回引用)
Date& operator+=(int day) {
if (day < 0) {
return *this -= (-day); // 转成减法
}
_day += day;
// 处理进位(日->月->年)
while (_day > GetMonthDay(_year, _month)) {
_day -= GetMonthDay(_year, _month);
_month++;
if (_month > 12) {
_year++;
_month = 1;
}
}
return *this;
}
// 7. 日期+天数(不修改当前对象,返回新对象)
Date operator+(int day) {
Date temp(*this); // 拷贝当前对象
temp += day; // 复用+=逻辑
return temp;
}
// 8. 日期-=天数(修改当前对象,返回引用)
Date& operator-=(int day) {
if (day < 0) {
return *this += (-day); // 转成加法
}
_day -= day;
// 处理借位(日->月->年)
while (_day < 1) {
_month--;
if (_month < 1) {
_year--;
_month = 12;
}
_day += GetMonthDay(_year, _month);
}
return *this;
}
// 9. 日期-天数(不修改当前对象,返回新对象)
Date operator-(int day) {
Date temp(*this);
temp -= day;
return temp;
}
// 10. 前置++
Date& operator++() {
*this += 1;
return *this;
}
// 11. 后置++
Date operator++(int) {
Date temp(*this);
*this += 1;
return temp;
}
// 12. 前置--
Date& operator--() {
*this -= 1;
return *this;
}
// 13. 后置--
Date operator--(int) {
Date temp(*this);
*this -= 1;
return temp;
}
// 14. 比较运算符重载(==)
bool operator==(const Date& d) const {
return _year == d._year && _month == d._month && _day == d._day;
}
// 15. 比较运算符重载(!=)
bool operator!=(const Date& d) const {
return !(*this == d);
}
// 16. 比较运算符重载(<)
bool operator<(const Date& d) const {
if (_year < d._year) {
return true;
} else if (_year == d._year && _month < d._month) {
return true;
} else if (_year == d._year && _month == d._month && _day < d._day) {
return true;
}
return false;
}
// 17. 比较运算符重载(<=)
bool operator<=(const Date& d) const {
return *this < d || *this == d;
}
// 18. 比较运算符重载(>)
bool operator>(const Date& d) const {
return !(*this <= d);
}
// 19. 比较运算符重载(>=)
bool operator>=(const Date& d) const {
return !(*this < d);
}
// 20. 日期-日期(返回天数差,d1 - d2 = 相差天数)
int operator-(const Date& d) const {
Date max = *this;
Date min = d;
int flag = 1;
if (*this < d) {
max = d;
min = *this;
flag = -1;
}
int dayCount = 0;
while (min < max) {
min++;
dayCount++;
}
return dayCount * flag;
}
// 打印日期
void Print() const {
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
// 测试代码
int main() {
Date d1(2024, 5, 22);
Date d2(2024, 6, 1);
// 测试日期+
Date d3 = d1 + 10;
cout << "d1 + 10 = ";
d3.Print(); // 输出:2024-6-1
// 测试日期-
Date d4 = d2 - 10;
cout << "d2 - 10 = ";
d4.Print(); // 输出:2024-5-22
// 测试++
Date d5 = ++d1;
cout << "++d1 = ";
d5.Print(); // 输出:2024-5-23
Date d6 = d1++;
cout << "d1++ = ";
d6.Print(); // 输出:2024-5-23
cout << "d1 = ";
d1.Print(); // 输出:2024-5-24
// 测试比较运算符
cout << "d1 < d2: " << (d1 < d2) << endl; // 输出:1(true)
// 测试日期差
int diff = d2 - d1;
cout << "d2 - d1 = " << diff << "天" << endl; // 输出:9天
return 0;
}
cpp
d1 + 10 = 2024-6-1
d2 - 10 = 2024-5-22
++d1 = 2024-5-23
d1++ = 2024-5-23
d1 = 2024-5-24
d1 < d2: 1
d2 - d1 = 9天
8.2 关键注意点
- 日期合法性校验:构造函数中校验年、月、日是否合法,避免非法日期;
- 闰年判断:
GetMonthDay中通过(year%4==0&&year%100!=0)||(year%400==0)判断; - 进位 / 借位处理:
+=/-=中循环处理日、月、年的进位 / 借位; - 代码复用:
+复用+=,-复用-=,减少冗余; - const 成员函数:比较运算符、Print 等不修改对象的函数,均设为 const 成员函数,支持 const 对象调用。
九、学习总结与建议
- 核心逻辑:本章围绕 "默认成员函数" 和 "运算符重载" 展开,日期类是实战核心,需掌握 "资源管理" 和 "语法规则" 两大关键点;
- 重点突破:
- 构造 / 析构 / 拷贝构造 / 赋值重载:何时显式实现(资源申请)、浅拷贝 vs 深拷贝;
- 运算符重载:前置 ++/ 后置 ++ 的区别、日期加减的进位 / 借位、比较运算符的逻辑;
- 日期类实现:闰年判断、月份天数计算、日期差计算的核心算法;
- 学习方法:
- 亲手运行日期类代码,修改参数测试边界情况(如 2 月 29 日、12 月 31 日);
- 对比记忆:拷贝构造 vs 赋值重载、前置 ++vs 后置 ++、+vs+=;
- 聚焦面试:日期类实现(高频笔试题)、const 成员函数调用规则、运算符重载禁止情况;
- 避坑清单:
- 日期类必须校验合法性,否则会出现逻辑错误;
- 运算符重载不能改变内置类型含义,不能创建新运算符;
- 涉及资源申请的类,必须显式实现深拷贝,否则崩溃;
- 后置 ++ 必须返回值,前置 ++ 返回引用。