借鉴了网上几个大牛的文章,忘了留链接,表示抱歉,这里总结如下:
总:
原则上是先调用基类构造函数,再成员对象的构造函数,再自身构造函数
析构函数调用顺序总是与构造函数顺序相反。特殊是虚继承(优先级高,并可能只执行一次构造)和静态变量
静态成员属于类作用域,但不属于类对象,和普通的static变量一样,程序一运行就分配内存并初始化,生命周期和程序一致。
所以,在类的构造函数里初始化static变量显然是不合理的。
静态成员其实和全局变量地位是一样的,只不过编译器把它的使用限制在类作用域内(不是类对象,它不属于类对象成员),要在类的定义外(不是类作用域外)初始化,在类外初始化且不能再带有static关键字。
二:具体
class 派生类名:继承方式1 基类名1,继承方式2 基类名2,....
{
//派生类成员定义
};
对每个基类可以用不同的继承方式,默认继承方式为private。
在多重继承中,派生类的构造函数与单继承下派生类构造函数相似,它必须负责该派生类所有基类构造函数以及对象成员(如果有的话)构造函数的调用。同时,派生类的参数必须包含完成所有基类、对象成员以及派生类中新增数据成员初始化所需的参数。派生类构造函数执行顺序如下:
(1)所有基类的构造函数,多个基类构造函数的执行顺序取决于定义派生类时所指定的顺序(左到右),与派生类构造函数中所定义的成员初始化列表的参数顺序无关;
(2)对象成员的构造函数; (类中非静态成员按其声明顺序初始化,同上,也与构造函数那个:后的顺序无关无关)
(3)派生类本身的构造函数。
加上虚基类后,它的初始化在语法上与一般多继承的初始化是相同的,但在调用构造函数的顺序上有点差别。
(1)先调用虚基类构造函数,然后调用非虚基类的构造函数(同级别的自然按照声明顺序)。
(2)当同一层有多个虚基类,按照他们的声明顺序调用它们的构造函数;
(3)当虚基类b是由非虚基类a派生时,则先调用非虚基类a构造函数,再调用派生类b构造函数。(就是对虚而言也是先调用基类后派生类)
脑补:
定义:
虚继承和虚基类的定义。 虚继承:在继承定义中包含了virtual关键字的继承关系; 虚基类:在虚继承体系中的通过virtual继承而来的基类,需要注意的是: struct CSubClass : public virtual CBase {}; 其中CBase称之为CSubClass 的虚基类,而不是说CBase就是个虚基类,因为CBase还可以不不是虚继承体系 中的基类。
虚基类是为了防止多继承产生问题,比如一个基类可能会被同一个子类继承好几次,有了虚基类,那么这个基类就不会在对象内存布局上重复出现了。然后再看这句话,结合前面的描述,我们可以这样理解。
class A //基类A
class B:public A //B继承A
class C:public A,B //C继承A,也继承B,此处A应该为虚继承,否则A就会被继承两次,因为B继承A
性能
由于有了间接性和共享性两个特征,所以决定了虚继承体系下的对象在访问时必然会在时间和空间上与一般情况有较大不同。
(1)时间 在通过继承类对象访问虚基类对象中的成员(包括数据成员和函数成员)时,都 必须通过某种间接引用来完成,这样会增加引用寻址时间(就和虚函数一样)。
(2) 空间 由于共享所以不同在对象内存中保存多份虚基类子对象的拷贝,这样较之多继承节省空间。
下面继续
例1:
class X:public Y,virtual public Z
{
}
X one;
将产生如下调用顺序:
Z()
Y()
X()
这里Z是X的虚基类,故先调用Z的构造函数,再调用Y的构造函数,最后才调用派生类X自己的构造函数.
例2(注意其两个虚继承时base1构造一次):
class base1
{
....
};
class base2
{
....
};
class level1:public base2,virtual public base1
{
....
};
class level2:public base2,virtual public base1
{
....
};
class toplevel1:public level1,virtual public level2
{
....
};
toplevel1 view;
当产生对象view时,将产生如下调用次序:
base1()
base2()
level2()
base2()
level1()
toplevel1()
toplevel1有两个基类:一个是虚基类level2,l另一个是非虚基类level1.根据规定:应先执行levevl2的构造函数;level2也有两个基类,一个实虚基类base1,另一个是非虚基类base2,应先执行base1的构造函数,再执行base2的构造函数,最后执行level2的构造函数。toplevel1然后执行level1的构造函数,而level1又有两个基类,base1是虚基类,无需再执行其构造函数,base2是非虚基类,因此要先执行base2的构造函数,然后执行level1的构造函数。最后执行toplevel1的构造函数。上例中,对于toplevel1的对象而言,base1是level1的虚基类。