构造函数
派生类的构造函数执行先后原则是顶级基类到自身,自顶向下的总体过程。而有一些值得注意的“特殊情况”
- 多继承的时候,构造函数执行的顺序是按类定义的时候基层的顺序,而不是构造函数的定义的顺序。
class Derived : public Base1, public Base2 {}
原因可能是编译器编译生成类结构的时候,按定义类的顺序建立相应堆结构,而堆需要从底层到顶层一层层的构造才行,因此是顺序是一定的,而构造函数的定义是一个匹配过程。
另外说明,类的字段即类的成员变量也是有先后的,其构造顺序是按声明的先后顺序而定的。 - 当继承的父类是一个虚基类的派生类的时候,该虚基类的构造是由最后的派生类完成,即本身。这是为了避免重复构造虚基类。
而这里就出现一个新的需要注意的问题——当所继承的两个或以上的父类们,祖先上层有交集且不是虚继承,那么那个交集的类会被构造两次(如果这个交集的类的构造模式不是singleton模式),这样就可能导致你引用的祖先成员变量不一定是你所想的,所以需要注意。
而虚基类就是解决这个问题,但同时出现新的问题,比如虚基表带来的额外空间消耗;当虚基类没有虚函数时由虚基类向下转化(父类转成字类)的时候会出现错误(因为虚基表没有虚基类的详细信息)。参考链接,他在虚基类这方面写的很明白 - 一个关于编译的问题——派生类只能直接调用直属父类,否则回报错。原因就是避免重复构造的额外开销。