1

継承を仮想に変更して、ダイヤモンドの継承を解決しました。

残念ながら、それは私のコンストラクターを壊します。それ以外の場合は、ダイヤモンドの継承が問題になります。

ダイヤモンドの片側:

TModuleBase -> TServerModuleBase -> MyModule

MyClass は基本クラスを継承します

     class MyModule :
         public TServerModuleBase
     {
     ...
     }

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


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

TModuleBase と TServerMosuleBase には 2 つの可能なコンストラクタがあるため (違い: サーバーは公開されていませんが、保護されています)。

    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

最も派生したコンストラクター ( ) から仮想ベース コンストラクターを呼び出す必要がありますMyModulector-initialiserでのTModuleBase(QString)呼び出しは単に無視され、デフォルトの構成を試みます(明示的に呼び出していないため)。TServerModuleBase(QString) TModuleBaseMyModule

仮想継承から通常の継承に変更するTServerModuleBase()と、適切なコンストラクターが呼び出されます (ただし、ベースのコピーが 2 つあるため、2 回呼び出されます)。

最も派生したコンストラクターで基本コンストラクターを呼び出す必要がある理由は、コンパイル時に基本クラスの場所が不明TServerModuleBaseであるが、MyModule.

于 2013-10-02T09:41:07.457 に答える