2010-12-19 1 views
2

以下のコードの子コンストラクタは、親コンストラクタを呼び出して初期化します。しかし、これは実装の詳細がParent内に隠れているはずですが、ChildがGrandparentコンストラクタも呼び出しなければ、コードはコンパイルされません。私はChildクラスのユーザーにこのディテールを公開したくはありません。今後変更される可能性があります。下のコードをどのように動作させるには?C++で祖父母のコンストラクタを呼び出すことを避けるにはどうすればよいですか?

私は「プライベート」に継承を変更しようとしましたが、チャイルドコンストラクタはまだプライベート継承の目的をいくらか打ち負かしているこのプライベートアレンジメントについて知っていることが期待されていました。

提案がありますか?

#include <iostream> 

class MyObject { 
    public: 
    MyObject(int i) { 
     std::cout << "MyObject(" << i << ") constructor" << std::endl; 
    } 
}; 

class Grandparent { 
    public: 
    Grandparent(MyObject i) 
    { 
    }; 
}; 

class Parent: virtual public Grandparent { 
    public: 
    Parent(int j) : 
     Grandparent(MyObject(j)) 
    { 
    }; 
}; 

class Child: virtual public Parent { 
    public: 
    Child() : 
     //Grandparent(MyObject(123)), // Won't work without this 
     Parent(5) 
    { 
    }; 
}; 

int main(void) 
{ 
    Child c; 
    return 0; 
} 
$ g++ -o test test.cpp 
test.cpp: In constructor ‘Child::Child()’: 
test.cpp:29: error: no matching function for call to ‘Grandparent::Grandparent()’ 
test.cpp:12: note: candidates are: Grandparent::Grandparent(MyObject) 
test.cpp:10: note:     Grandparent::Grandparent(const Grandparent&) 
+0

[gcc C++仮想継承問題]の複製が可能です。(http://stackoverflow.com/questions/2126522/gcc-c-virtual-inheritance-problem) –

答えて

5

継承が仮想であるためです。 Childクラスは、多重継承されたクラスのインスタンスを管理する必要があるため、仮想継承は実装の詳細にはなりません。通常の継承を使用する場合、これは問題ではありません。

+0

これは問題のようです - ありがとう!なぜこれが事実であるかについてのあらゆるポインタ/推論? – Malvineous

+0

@Malvineous、[この記事](http://www.learncpp.com/cpp-tutorial/118-virtual-base-classes/)は、私が見つけ出すのに最適な説明です。基本的には、複数の継承の場合でも仮想ベースのコンストラクタは(通常のコンストラクタチェーンのうち、最も派生したクラスによって)一度だけ呼び出されることを保証することです。 –

+0

@Sergey:なぜこれがこのようなものなのか理解しています。 – Malvineous

1

仮想継承が削除されても問題なく動作します。

関連する問題