1

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

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

钻石的一侧:

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++。是的,我做了干净的构建。很多次。

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

4

1 回答 1

1

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

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

您需要在最派生的构造函数中调用基构造函数的原因是因为在编译时基类的位置是未知的,TServerModuleBase但它是已知的MyModule

于 2013-10-02T09:41:07.457 回答