虚继承中对象的构造顺序
虚基类的构造
首先虚基类的构造是通过最底层的派生类初始化,并且继承体系的每个类都可能在某个时刻成为最低层的派生类
class A{
public:
A(){}
}
class B:virtual public A{
public:
B(){}
}
class C:virtual public A{
public:
C(){}
}
class D:public B,public C{
public:
D(){}
}
就比如说上面这一个例子,
B b; //b是最底层基类,由b直接构造虚基类a(b先通过a的默认构造函数构造其虚基类a子对象,随后构造自身)
D d; //在这种情况下,d是最低层基类,由d直接构造基类c(d先通过a的默认构造函数构造其虚基类a子对象,随后分别通过b和c的默认构造函数构造其基类b和c子对象,最后构造自身
即使a不是d的直接基类,d的构造函数也可以初始化a
需要注意的一点是,如果最低层基类没有显示地初始化其虚基类子类对象,则虚基类的默认构造函数将会被调用。如果最底层基类没有默认构造函数,则代码会发生错误。(在本示例中d非显示的,通过调用a的默认构造函数构造其虚类子对象a)
构造函数的顺序
程序示例
-
首先初始化对象的虚基类子部分
如果一个类含有多个虚基类,则这些虚的子对象按照它们在派生列表中出现的顺序从左向右构造
编译器按照直接基类的声明顺序依次对直接基类进行检查,以确定其中是否含有虚基类。如果有,则先构造虚基类。(本例在直接基类level1中有虚基类base1,因此先构造base1而不是base2和level12;在构造完base1后,按照从左至右的规则构建虚基类level12子对象,因为level12子对象的构建需要先构建level12的虚基类子对象base2,所以构造顺序是base2、level12;在构造完所有虚基类子对象后,构造非虚类子对象) -
接下来按照直接基类在派生列表中出现的次序依次对其进行初始化
(先构建level11非虚类子对象,level11通过base2的构造函数构造base2子对象后构建其自生,最后toplevel构造自身)
析构函数的调用顺序和构造函数相反