2016-05-14 15 views
7

次のコードは、クラスのみImplBであなたが行のコメントを外した場合階層インタフェースと実装

virtual void FuncA() { ImplA::FuncA(); } 

を動作しますが、そうでなければ私はコンパイラエラーを取得:それは取得しない理由を

cannot instantiate abstract class ... FuncA(void)' : is abstract

質問です継承されたImplAからFuncA()を実装しますか?

class InterfaceA { 
public: 
    virtual void FuncA()=0; 
}; 

class InterfaceB : public InterfaceA { 
public: 
    virtual void FuncB()=0; 
}; 

class ImplA : public InterfaceA { 
public: 
    virtual void FuncA() { printf("FuncA()\n"); } 
}; 

class ImplB : public ImplA, public InterfaceB { 
public: 
    // virtual void FuncA() { ImplA::FuncA(); } 
    virtual void FuncB() { printf("FuncB()\n"); } 
}; 

{ 
    ImplB *b = new ImplB(); 
    InterfaceA *A= b; 
    A->FuncA(); 
    InterfaceB *B= b; 
    B->FuncB(); 
    B->FuncA(); 
} 
+0

あなたはオーバーライドする必要がある2つの純粋仮想関数を持つ抽象である 'InterfaceB'を継承しているからです。 –

+0

クラスImplA:public InterfaceA { public: 仮想void FuncA(){printf( "FuncA()\ n"); } }; – perry

+0

クラスImplAは次のように修正されます。結果は同じ – perry

答えて

3

あなたは多重継承で「ダイヤモンド」問題のインスタンスを打ってきました。 "仮想"継承を使用する必要があります(継承時にキーワードvirtualを追加することになります)

問題は、ImplBに基本クラスInterfaceAへの2つのパスがあることです。しかし、あなたの意図は、インターフェイスが実装を提供していないということです。したがって、これをコンパイラに示す必要があるため、純粋な仮想関数を統一することができます。より良い説明のために

http://www.cprogramming.com/tutorial/virtual_inheritance.html

私はあなたのインターフェイスを継承する場合、仮想追加するようにコードを修正しました。これで、コメントされた行であってもコンパイルできます。また、仮想デストラクタが不足していると思いますので、他にもいくつかの問題があります。このコードは、FuncAのコメントを外さずにコンパイルされます。

#include <cstdio> 

class InterfaceA { 
public: 
    virtual void FuncA()=0; 
}; 

class InterfaceB : public virtual InterfaceA { 
public: 
    virtual void FuncB()=0; 
}; 

class ImplA : public virtual InterfaceA { 
public: 
    virtual void FuncA() { printf("FuncA()\n"); } 
}; 

class ImplB : public ImplA, public virtual InterfaceB { 
public: 
    // virtual void FuncA() { ImplA::FuncA(); } 
    virtual void FuncB() { printf("FuncB()\n"); } 
}; 

int main() 
{ 
    ImplB *b = new ImplB(); 
    InterfaceA *A= b; 
    A->FuncA(); 
    InterfaceB *B= b; 
    B->FuncB(); 
    B->FuncA(); 
} 
+1

多くの多くの多くのありがとう!これはしばらくの間私を悩ませている、あなたは完全に釘付け。私はあなたの借金にいる。 – perry

0

多重継承は、あなたが同じ名前のメソッドを持っていますが、それは彼らが同じことはありません複数のクラスから継承することができ、「ミックスイン」

ではありません。

仮想クラスから継承するものは、その親の純粋な仮想関数を実装する必要があります。

メソッド名のスコープが指定されていないと、共有名を持つメソッドの実装に互換性がないため、相互に排他的であった親クラスの組み合わせで結ばれる可能性があります。

私はImplBでusing ImplA::FuncA;を置くことは、しかし、それを解決しないことに少し驚いています:https://gcc.godbolt.org/