类如果没有显式的声明以下六种函数,编译器会自动添加(需要的时候才添加),而且都不会被派生类继承:
- 构造函数
- 析构函数
- 拷贝构造函数
- 重载赋值操作符函数
- 取址运算符重载函数
- const 取址运算符重载函数
class A{
public:
A();
~A();
A(const A &);
A& operator=(const A &);
A* operator&();
const A * operator&() const;
}
拷贝构造函数和重载操作符调用时机
如果一个对象在实例化的时候(即在声明的时候将一个已经存在的对象赋值给他),调用的是拷贝构造函数;如果对象已经存在,将另一个对象赋值给他,调用的就是重载赋值操作符函数。在传递参数或者是函数返回值时,如果不是引用,则会调用拷贝构造函数。
#include <iostream>
using namespace std;
class CTest
{
public:
CTest(){}
~CTest(){}
CTest(const CTest &test)
{
cout<<"copy constructor."<<endl;
}
void operator=(const CTest &test)
{
cout<<"operator="<<endl;
}
void Test(CTest test)
{}
CTest Test2()
{
CTest a;
return a;
}
void Test3(CTest &test)
{}
CTest &Test4()
{
CTest *pA = new CTest;
return *pA;
}
};
int main()
{
CTest obj;
CTest obj1(obj); // 调用复制构造函数
obj1 = obj; // 调用重载赋值操作符
/* 传参的过程中,要调用一次复制构造函数
* obj1入栈时会调用复制构造函数创建一个临时对象,与函数内的局部变量具有相同的作用域
*/
obj.Test(obj1);
/* 函数返回值时,调用复制构造函数;将返回值赋值给obj2时,调用重载赋值操作符
* 函数返回值时,也会构造一个临时对象;调用复制构造函数将返回值复制到临时对象上
*/
CTest obj2;
obj2 = obj.Test2();
obj2.Test3(obj); // 参数是引用,没有调用复制构造函数
CTest obj3;
obj2.Test4(); // 返回值是引用,没有调用复制构造函数
return 0;
}
重载操作符
- 带点的操作符不可重载:
.
,.*
,::
,?:
- 重载
-=
,+=
,=
的时,返回值应该为引用。
函数调用顺序
- 调用基类构造函数;多继承的时候按照派生列表顺序。
- 成员变量声明的顺序初始化,而不是初始化列表
- 构造函数