- 先执行静态成员的构造函数,如果静态成员只是在类定义中声明了,而没有实现,是不用构造的。必须初始化后才执行其构造函数。
- 任何抽象基类的构造函数按照它们被继承的顺序构造(不是初始化列表中的顺序)
- 任何虚拟基类的构造函数按照它们被继承的顺序构造(不是初始化列表中的顺序)
- 任何非虚拟基类的构造函数按照它们被继承的顺序构造(不是初始化列表中的顺序)
- 任何成员对象的构造函数按照它们声明的顺序构造
- 类自己的构造函数
成员列表初始化 (同成员变量对象的初始化)
- 初始化列表应该在构造函数的地方使用;
- 构造函数参数列表之后函数体之前定义初始化列表;
- 其作用就是对成员变量进行初始化;
注意事项(避免 bug 很重要):
- 成员的初始化顺序与成员的声明顺序相同;
- 成员的初始化顺序与初始化列表中的位置无关;
- 初始化列表先于构造函数的函数体执行;
当构造函数的函数体开始执行的时候,对象已经创建完毕了,执行构造函数的函数体仅仅是为了初始化我们这个对象的状态而已;
所以说初始化列表既然是用于初始化,那么必须在我们这个类对象创建的同时来进行执行,而不应该是对象已经创建好了才来进行一系列的初始化工作,这一点是有明确差异的,这个差异也就是初始化和赋值之间的差异;
重载构造函数间调用——委托构造函数
C++11新标准扩展了构造函数初始值的功能,所以委托构造函数就出现了。
一个委托构造函数使用它所属的类的其他构造函数执行自己的初始化过程,或者说它把自己的一些(或者全部)职责委托给了其他构造函数。
和其他构造函数一样,一个委托构造函数也有一个成员初始值的列表和一个函数体。
在委托构造函数内,成员的初始值列表只有一个唯一的入口,就是类名本身。
和其他成员初始值一样,类名后面紧跟圆括号括起来的参数列表,参数列表必须与类中另外一个构造函数匹配。
在使用委托构造函数时,不能再进行成员列表初始化,而只能在函数体内进行初始化其他成员变量。那么我们在委托其他构造函数构造对象时,一些成员变量以默认值构造了,在函数体内进行初始化就不叫初始化了,只能叫重新赋值了。见下面例子:
class A
{
private:
int a;
int b;
char c;
char d;
public:
A(int num0,int num1,char C):a(num0),b(num1),c(C){}
A(int num0,char C):A(num0,0,C){}//b默认初始化为0
A(int num0):A(num0,'p'){b=1;}//b重新赋值为1
void getMembers()
{
cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
}
};
在委托第二个构造函数构造时,b被初始化为0,这里我们在函数体内重新赋值为1,那么b到底是0还是1呢?结果是1。
函数体内的初始化要晚于成员列表初始化,即委托其他构造函数构造完后,在进行函数体内的赋值。