虚拟继承打破了初始化列表显式构造函数调用

时间:2013-10-02 09:37:30

标签: c++ inheritance constructor

我已经通过将继承更改为虚拟来解决钻石继承问题。

不幸的是它破坏了我的构造函数。 钻石继承在其他情况下是问题。

钻石的一面:

TModuleBase - > TServerModuleBase - > MyModule的

MyClass继承基类

     class MyModule :
         public TServerModuleBase
     {
     ...
     }

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


     QString MyModule::ModuleName(void)
     {
        return "MyModuleName";
     }

由于TModuleBase和TServerMosuleBase有两个可能的构造函数(区别:服务器不公开但受保护):

    class TModuleBase
    {
    public:
        explicit TModuleBase(void);
        explicit TModuleBase(QString moduleName);
    }


    class TServerModuleBase
        : public virtual TModuleBase
    {
    protected:
        explicit TServerModuleBase(void);
        explicit TServerModuleBase(QString moduleName);
    }

    TServerModuleBase::TServerModuleBase(void)
        : TModuleBase()
    {
    }
    TServerModuleBase::TServerModuleBase(QString moduleName)
        : TModuleBase(moduleName)
    {
    }

当调用MyModule构造函数时,它调用无效的构造函数:

    TServerModuleBase(ModuleName()) //expected
    TServerModuleBase()             //called

当我换回时

    class TServerModuleBase
        : public virtual TModuleBase

进入:

    class TServerModuleBase
        : public TModuleBase

构造函数选择按预期工作。

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

感谢您的关注,时间和帮助。

1 个答案:

答案 0 :(得分:1)

您需要从派生程度最高的构造函数(MyModule)调用虚拟基础构造函数。 TModuleBase(QString) ctor-initialiser 中的TServerModuleBase(QString)电话被忽略,然后尝试在TModuleBase中默认构建MyModule(因为你没有' t明确地称之为。

当你从虚拟继承更改为普通继承时,TServerModuleBase()会调用正确的构造函数(虽然它调用它两次,因为有两个副本的副本)。

您需要在派生程度最高的构造函数中调用基本构造函数的原因是因为在编译时TServerModuleBase不知道基类的位置,但MyModule已知它。< / p>