目录
默认成员函数
如果一个类中什么成员都没有,简称为空类。
空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员
函数。
构造函数
构造函数的主要任务并不是开空间创建对象,而是初始化对象。
其特征如下:
1. 函数名与类名相同。
2. 无返回值。
3. 对象实例化时编译器自动调用对应的构造函数。
4. 构造函数可以重载。
例子
class Class {
int num;
public:
// 默认构造函数
Class() {
num = 0;
}
// 带参数的构造函数
Class(int n) {
num = n;
}
// 缺省的默认构造函数
Class(int n=1){
num = n;
}
// 初始化列表
Class(int n)
:num(n)
{}
};
int main() {
// 创建对象及调用构造函数
Class obj1; // 调用默认构造函数
Class obj2(10); // 调用带参数的构造函数
// 调用其他成员函数
int num1 = obj1.getNum(); // 返回0
int num2 = obj2.getNum(); // 返回10
return 0;
}
【注意】
1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
- 引用成员变量
- const成员变量
- 自定义类型成员(且该类没有默认构造函数时)
3. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后
次序无关
析构函数
析构函数是一种特殊的成员函数,它在对象的生命周期结束时被调用,用于释放对象所占用的资源。析构函数具有以下特征:
- 构造函数名称与类名称相同,前面加上波浪号(~)作为前缀。
- 析构函数没有返回类型,包括void。
- 析构函数没有参数。
- 每个类只能有一个析构函数。
- 如果没有显式定义析构函数,编译器会自动生成一个默认的析构函数。
拷贝构造函数
拷贝构造函数也是特殊的成员函数,其特征如下:
- 拷贝构造函数是构造函数的一个重载形式。
- 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
- 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
- 拷贝构造函数典型调用场景:
- 使用已存在对象创建新对象
- 函数参数类型为类类型对象
- 函数返回值类型为类类型对象
注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请
时,则拷贝构造函数是一定要写的,否则就是浅拷贝。
//浅拷贝
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
赋值运算符重载
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
注意:
- 不能通过连接其他符号来创建新的操作符:比如operator@
- 重载操作符必须有一个类类型参数
- 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
- 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
- .* :: sizeof ?: . 注意以上5个运算符不能重载
Date& operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
// 前置++
Date& operator++()
{
_day += 1;
return *this;
}
// 后置++
// C++规定:后置++重载时多增加一个int类型的参数
Date operator++(int)
{
Date tmp(*this);
_day += 1;
return tmp;
}
取地址及const取地址操作符重载
这两个默认成员函数一般不用重新定义
Date* operator&()
{
return this ;
}
const Date* operator&()const
{
return this ;
}
友元
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在
类的内部声明,声明时需要加friend关键字。
class Date
{
friend ostream& operator<<(ostream& _cout, const Date& d);
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
_cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
注:友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。