C++ 虚拟继承中断初始化列表显式构造函数调用

C++ 虚拟继承中断初始化列表显式构造函数调用,c++,inheritance,constructor,C++,Inheritance,Constructor,我已通过将继承更改为虚拟来解决菱形继承问题 不幸的是,它破坏了我的构造函数。 钻石继承是另一种情况下的问题 钻石的一面: TModuleBase->TServerModuleBase->MyModule MyClass继承基类 class MyModule : public TServerModuleBase { ... } MyModule::MyModule() : TServerModuleBase(M

我已通过将继承更改为虚拟来解决菱形继承问题

不幸的是,它破坏了我的构造函数。 钻石继承是另一种情况下的问题

钻石的一面:

TModuleBase->TServerModuleBase->MyModule

MyClass继承基类

     class MyModule :
         public TServerModuleBase
     {
     ...
     }

     MyModule::MyModule()
         : TServerModuleBase(ModuleName())
     {
     }


     QString MyModule::ModuleName(void)
     {
        return "MyModuleName";
     }
由于TModuleBase和TServerMosuleBase有两个可能的构造函数(区别:服务器不是公共的,而是受保护的):

调用MyModule构造函数时,会调用无效构造函数:

    TServerModuleBase(ModuleName()) //expected
    TServerModuleBase()             //called
当我回头的时候

    class TServerModuleBase
        : public virtual TModuleBase
进入:

    class TServerModuleBase
        : public TModuleBase
构造函数选择按预期工作

我使用的是g++。是的,我做了干净的建筑。很多次


谢谢你的关注、时间和帮助

您需要从最派生的构造函数(
MyModule
)调用虚拟基构造函数。
TServerModuleBase(QString)
ctor初始化器中的
TModuleBase(QString)
调用被忽略,然后它尝试在
MyModule
中默认构造
TModuleBase
(因为您没有显式调用它)

当您从虚拟继承更改为普通继承时,
TServerModuleBase()
确实调用了正确的构造函数(尽管它调用了两次,因为有两个基的副本)


您需要在最派生的构造函数中调用基类构造函数的原因是,在编译时,
TServerModuleBase
不知道基类的位置,但
MyModule
知道基类的位置。您需要从最派生的构造函数中调用虚拟基类构造函数(
MyModule
)。
TServerModuleBase(QString)
ctor初始化器中的
TModuleBase(QString)
调用被忽略,然后它尝试在
MyModule
中默认构造
TModuleBase
(因为您没有显式调用它)

当您从虚拟继承更改为普通继承时,
TServerModuleBase()
确实调用了正确的构造函数(尽管它调用了两次,因为有两个基的副本)


您需要在最派生的构造函数中调用基类构造函数的原因是,在编译时,
TServerModuleBase
不知道基类的位置,但是
MyModule
知道基类的位置,那么为什么忽略关键字explicit呢?如果未显式调用构造函数,我希望编译器会抛出一些错误。@urkon
explicit
仅在使用复制初始化语法(如
tx=10
)时适用。一个
显式的
构造函数会阻止这种情况,并迫使您编写
tx(10)
。关键字对这种情况没有任何作用。为什么忽略关键字“explicit”?如果未显式调用构造函数,我希望编译器会抛出一些错误。@urkon
explicit
仅在使用复制初始化语法(如
tx=10
)时适用。一个
显式的
构造函数会阻止这种情况,并迫使您编写
tx(10)
。关键字对本例没有任何作用。
    class TServerModuleBase
        : public TModuleBase