2011-12-19 22 views
0

はおそらく最良の例で説明した:複数の仮想継承の曖昧

struct A 
{ 
    virtual void foo() = 0; 
}; 


struct B 
{ 
    virtual void foo() = 0; 
}; 


struct C : A, B 
{ 
    // Implementation of A::foo 
    void A::foo(); 

    // Implementation of B::foo 
    void B::foo(); 
}; 


// Define here; howto? 

私はそれが実装するために約6基底クラスがあります(この例では現実的ではないのですが、私はクラスでインライン関数を定義することができます承知していますすべて40 +メソッドあり)

-

どうやら明確ではありませんでした。疑問は直接です:どのようにあいまいさの問題を引き起こすことなく継承されている両方のfoo()メソッドを定義するのですか?

次は確かに

void C::foo() { /* etc */ } 

これは:: FOO(の実装を定義します)まだBの何:: FOOを()に動作しますか?

- 念頭に、私はC.

PSの宣言内にメソッドを定義したくない、まったくこの方法で問題をモデル化するための理由は

(COM/OLE)あらかじめ定義されています予想通り

struct A { virtual int foo() = 0; }; 
struct B { virtual int foo() = 0; }; 

struct C : A, B 
{ 
    int A::foo() { return 1; } 
    int B::foo() { return 2; } 
}; 


void main() 
{ 
    C* p = new C(); 

    cout << ((A*) p)->foo(); 
    cout << ((B*) p)->foo(); 
} 
+1

質問がありますか? –

+1

この例では仮想継承を持っていません。仮想関数を持つクラスを複数継承しています。 – Mat

+1

問題はなんですか? – ScarletAmaranth

答えて

4

2つの基本クラスで定義された同じシグネチャを持つ2つの関数に対して、別々のオーバーライドを提供することはできません。 (考えることができるように、クラス内でインラインで定義することはできません)。ベース・クラス・インターフェースの一実施各々が2つの内部クラスを構成することにより、複数の継承を避けることができ、あるいは

struct ABodge : A 
{ 
    void foo() {A_foo();} 
    virtual void A_foo() = 0; 
}; 

struct BBodge : B 
{ 
    void foo() {B_foo();} 
    virtual void B_foo() = 0; 
}; 

struct C : ABodge, BBodge 
{ 
    void A_foo(); 
    void B_foo(); 
}; 

一つの可能​​性は、機能の名前を変更するために、中間ベースクラスを導入することである

class C 
{ 
public: 
    // Could probably be defined as `operator A&()`, etc. to look more like 
    // inheritance, but I usually prefer conversions to be explicit. 
    A  & asA()  {return a;} 
    A const & asA() const {return a;} 
    B  & asB()  {return b;} 
    B const & asB() const {return b;} 

private: 
    // These might need back-references to the 'C' that contains them. 
    struct AImpl : A {void foo();} a; 
    struct BImpl : B {void foo();} b; 
}; 
+0

あなたは、あなたがインラインでそれらを定義することはできないと言いますが、私はあなたが(MSVC以上で)できると主張し、私の問題は構文の意味論であると推測するので尋ねる理由です。 – Emjayen

+0

@ Matt.J:おそらくMSVCにはそれを可能にする非標準の拡張機能がありますが、標準のC++ではそうではありません。あなたのコードは[GCC](http://ideone.com/OQsYV)でコンパイルされません –

+0

私の編集を明確にするために、この非標準機能が正しいことを示していますか? – Emjayen

1

作品:これは、インラインにもかかわらず(MSVC)大丈夫です

struct A { virtual void foo() = 0; }; 
struct B { virtual void foo() = 0; }; 
struct C : A, B { virtual void foo(); }; 
void C::foo() { } 

C x;については、static_cast<A&>(x).foo()static_cast<B&>(x).foo()は、正確にはABという純仮想インターフェイスが約束しているとおり、x.foo()を期待通りに呼び出します。

+0

これは素晴らしいことですが、あいまいさの問題を解決する方法を示しているわけではありません。 – Emjayen

+0

@ Matt.J:あいまいさはないと思う*。問題は何ですか? –