8

興味深い多重継承の問題を理解しようとしています。

祖父母は、複数のメソッドを持つインターフェイス クラスです。

class A
{
public:
    virtual int foo() = 0;
    virtual int bar() = 0;
};

次に、このインターフェースを部分的に完成させる抽象クラスがあります。

class B : public A
{
public:
    int foo() { return 0;}
};

class C : public A
{
public:
    int bar() { return 1;}
};

私が使用したいクラスは、両方の親から継承し、ディレクティブを使用して、どのメソッドがどこから来る必要があるかを指定します。

class D : public B, public C
{
public:
    using B::foo;
    using C::bar;
};

DI をインスタンス化しようとすると、抽象クラスをインスタンス化しようとするとエラーが発生します。

int main()
{
    D d; //<-- Error cannot instantiate abstract class.

    int test = d.foo();
    int test2 = d.bar();

    return 0;
}

誰かが問題を理解し、部分的な実装を最大限に活用する方法を教えてもらえますか?

4

2 に答える 2

13

ダイヤモンドの継承はありません。BおよびC基本クラスは、から事実上継承しないため、Dそれぞれ独自の基本クラス サブオブジェクトを持ちます。AA

そのため、 にはD、実際に実装する必要がある 4 つの純粋仮想メンバー関数があります。 A::fooand A::barfromBA::fooand A::barfromCです。

おそらく仮想継承を使用したいと思うでしょう。クラス宣言と基本クラス リストは次のようになります。

class A
class B : public virtual A
class C : public virtual A
class D : public B, public C

仮想継承を使用したくない場合は、次の 2 つの純粋仮想関数をオーバーライドする必要がありますD

class D : public B, public C
{
public:
    using B::foo;
    using C::bar;

    int B::bar() { return 0; }
    int C::foo() { return 0; }
};
于 2011-05-03T02:31:35.817 に答える
-2

virtual適切に継承するには、基本クラスを作成する必要があります。一般的なルールは、すべての非プライベート メンバー関数と基本クラスは、virtual自分が何をしているのかを知っていて、そのメンバー/ベースの通常の継承を無効にしたい場合を除きます。

于 2011-05-03T02:37:17.600 に答える