虚拟基类的虚拟基类调用错误构造函数问题求助
虚拟继承下构造函数的调用规则问题解析
你碰到的这个问题其实是C++虚拟继承的核心规则在搞鬼——虚拟基类的构造函数必须由最派生类(也就是你代码里的Derived2)直接负责初始化,中间派生类(比如Derived1)对虚拟基类构造函数的调用会被编译器直接忽略。
先看你的最小复现代码:当你在main里构造Derived2时,Derived2的构造函数初始化列表只写了: Derived1(0),没有显式指定虚拟基类Base的构造方式,这时候编译器会自动调用Base的无参默认构造函数,也就是你看到的Base()输出。
解决方法
要让Base调用带参数的构造函数,你需要在最派生类的构造函数初始化列表里直接调用虚拟基类的带参数构造函数,修改后的Derived2类代码如下:
class Derived2 : virtual public Derived1 { public: Derived2() : Base(0), Derived1(0) { printf("Derived2()\n"); } ~Derived2() {} protected: Derived2(int value) : Base(value), Derived1(value) { printf("Derived2(%d)\n", value); } };
修改后运行程序,输出就会变成你预期的样子:
Base(0) Derived1(0) Derived2()
为什么会这样?
虚拟继承的设计初衷是解决多继承中同一个基类被多次继承导致的重复实例问题。为了保证虚拟基类只会被初始化一次,C++标准强制规定:虚拟基类的初始化必须由最终创建对象的最派生类完成。中间的派生类即使在初始化列表里写了对虚拟基类的调用,编译器也会忽略,因为它无法确定最派生类是否需要传递不同的参数。
回到你最开始提到的多文件复杂类结构场景:所有涉及虚拟继承的派生类,当你构造某个最派生类的时候,必须在它的构造函数初始化列表里显式调用所有直接和间接的虚拟基类的带参数构造函数,不能依赖中间父类去完成这个操作。
内容的提问来源于stack exchange,提问作者bugblatterbeast
相关产品推荐
相关产品推荐

