12

次のコードが与えられた場合 (仮想継承なし):

class A
{
public:
    virtual void f() = 0;
};

class B : public A
{
 public:
    virtual void f() {}
};

class C : public A
{
 public:
    virtual void f() {}
};

class D : public B, public C
{

/* some code */
};


int main()
{
    D d;
    return 0;
}

コードをコンパイルします。

一方、ここでは:

class A
{
public:
    virtual void f() = 0;
};

class B : virtual public A
{
    virtual void f() {}
};

class C : virtual public A
{
    virtual void f() {}
};

class D : public B, public C
{
    /* some code */
};


int main()
{
    D d;
    return 0;
}

コンパイラはコンパイル エラーを表示します。

no unique final overrider for 'virtual void A::f()' in 'D' . 

2 番目のコードで異なるのはなぜですか?

4

2 に答える 2

9

最初のシナリオ階層は次のものに対応します。

    F()   F()
     A     A
     |     |
 F() B     C F()
      \   /
        D 

タイプDのオブジェクトには2つのAサブオブジェクトがあるため、Dは抽象的ではありません。1つはBの格子を介してBによって具体化され、もう1つはCの格子を介して具体化されます。

Dのオブジェクトで関数F()を呼び出そうとしない限り、あいまいさはありません。

2番目のシナリオ階層は次のものに対応します。

       F()  
        A
      /   \
 F() B     C F()
      \   /
        D  

このシナリオでは、オブジェクトDには単一の基本クラスAサブオブジェクトがあり、そのサブオブジェクトの純粋仮想関数の実装をオーバーライドして提供する必要があります。


Guru Of The Week(GOTW)のハーブサッターの記事は、多重継承の良い読み物です。

  1. 多重継承パートI
  2. 多重継承パートII
  3. 多重継承パートIII
于 2011-08-28T09:19:50.190 に答える
7

仮想継承では、Dオブジェクトは単一の基底クラスAサブオブジェクトを持ちます。この単一のサブオブジェクトは、仮想関数の 2 つの異なる実装を持つことはできません。対照的に、仮想継承がなければ、Dオブジェクトには 2 つの別個の基本クラスAサブオブジェクトがあり、それぞれが関数の独自の実装を持っています (これは、Dオブジェクトでそれを呼び出そうとするまでは問題ありません。欲しいです)。

乾杯 & hth。

于 2011-08-28T09:10:22.240 に答える