C++类成员的默认函数
类和结构默认成员函数有六个
- 构造函数
- 拷贝构造函数
- 赋值运算符重载
- 析构函数
- 取地址运算符重载
- const修饰的取地址运算符重载
1. 构造函数
构造函数用于初始化成员变量,是特殊的成员函数,其特征有:
- 函数名和类名相同
- 无返回值
- 实例化对象时由系统自己调用 如果类定义中没有定义构造函数,c++编译器会自动产生一个无参的构造函数
- 如果自己定义了构造函数则编译器不会生成 无参的构造函数和全缺省的构造函数均为缺省构造函数,缺省构造函数只能有一个
- 构造函数的调用顺序是按声明顺序调用基类和类成员构造函数, 析构函数与之相反
class A{
}; //空类的大小是1
class Date{
public:
// 2.带参构造函数
Date(int year, int month, int day)
:_year(year)
,_month(month)
,_day(day)
,a()
{}
private:
int _year;
int _month;
int _day;
A a;
};
使用初始化成员列表初始化类成员变量,这种方式效率优于在构造函数内进行赋值初始化
在进入构造函数函数体前类成员已经通过初始化列表隐式初始化完成,如果在内部继续进行赋值会造成资源浪费
如类成员为自定义类型, 在初始化成员列表隐式初始化时调用其构造函数, 在内部赋值操作还会调用构造函数。
另外const成员或引用类型的成员只能在初始化列表初始化,因为const对象或引用类型只能初始化,不能对他们赋值。还有初始化列表的顺序按照类成员声明顺序进行初始化。
2. 拷贝构造函数
创建对象时使用同类对象来进行初始化,这时所用的构造函数称为拷贝构造函数,其特征:
- 拷贝构造函数其实是一个构造函数的重载。
- 拷贝构造函数的参数必须使用引用传参,使用传值方式会引发无穷递归调用。
- 若未显示定义,系统会默认生成一个拷贝构造函数, 拷贝构造函数会依次拷贝类成员进行初始化。
- 如果自己定义了拷贝构造函数,编译器将不会生成默认的构造函数
拷贝构造函数使用
class Date
{
public:
Date()
{}
// 拷贝构造函数
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
3. 析构函数
当一个对象的生命周期结束时,C++编译系统会自动调用一个成员函数,这个特殊的成员函数即析构函数(destructor)
构造函数是特殊的成员函数,其特征如下:
- 析构函数在类名加上字符~。
- 析构函数无参数无返回值。
- 一个类有且只有一个析构函数。若未显示定义,系统会自动生成析构函数。
- 对象生命周期结束时,C++编译系统系统自动调用析构函数。
- 析构函数主要完成对象的清理工作
class Array
{
public:
Array(size_t size = 10)
: _size(size)
, _a(0)
{
if (_size > 0)
{
_a = new int[size];
}
}
~Array()
{
if (_a)
{
delete[] _a;
_a = 0;
_size = 0;
}
}
private:
int* _a;
size_t _size;
};
4. 赋值运算符重载
赋值运算符重载的一种简单写法
// A = B
Array & operator=(Array d) //调用拷贝构造,生成一个和准备赋值对象(B)相同的对象
{
swap(_a, d._a); //将当前对象(A)和对象d的数据成员进行交换
_size = d._size;
return *this; //为了实现连续赋值因此返回值为一个对象的引用
} //函数运行完成后临时对象b被释放 即A对象的原来成员会被释放从而实现了赋值重载
5. 取址(&)运算符重载
Array * operator&()
{
return this;
}
6. const修饰的取址运算符重载
const Array* operator&() const
{
return this;
}