1

次のシナリオで何が起こるかわかりません。

class MBase {
    public:
       MBase(int) {}
       virtual char* vf() const = 0;
       virtual ~MBase() {}
};

class D1 : public MBase { //NOT VIRTUAL!!!
   public:
   D1() : MBase(1) {}
   char* vf() const { return "D1"; }
};

class D2 : virtual public MBase {
    public:
        D2() : MBase(2) {}
        char* vf() const { return "D2"; }
};

class Bottom : public D1, public D2 {
  public:
    char* vf() const { return "Bottom"; }
}

Base* b = new Bottom();  

ダイアモンドの元の定義では、D1 と D2 の両方が MBase から事実上継承していましたが、ここでは 1 つだけです。Bottom オブジェクトに 2 つの別個のサブオブジェクトが残っているので、コンパイラがどのサブオブジェクトを使用するかを認識できないため、最後の行はコンパイルされませんか?

4

2 に答える 2

2

これは、C++03標準のセクション10.1.4で指定されています。仮想ベースと非仮想ベースは独立しているため、それぞれ1つずつ存在します。

例を拡張すると、これを簡単に確認できます。

class MBase {
    public:
       MBase(int arg) { cerr << "MBase::MBase(" << arg << ")\n"; }
       virtual const char* vf() const = 0;
       virtual ~MBase() {}
};

class D1 : public MBase { //NOT VIRTUAL!!!
   public:
   D1() : MBase(1) {}
   const char* vf() const { return "D1"; }
};

class D2 : virtual public MBase {
    public:
        D2() 
        : MBase(2) // This doesn't get used in this example because
                   // it is the responsibility of the most-derived
                   // class to initialize a virtual base, and D2 isn't
                   // the most-derived class in this example.
        {
        }
        const char* vf() const { return "D2"; }
};

class Bottom : public D1, public D2 {
  public:
    Bottom() 
    : MBase(5) // D1 and D2 default constructors are called implicitly.
    { 
    }
    const char* vf() const { return "Bottom"; }
};

int main(int argc,char **argv)
{
  Bottom b;
  return 0;
}

出力:

MBase::MBase(5)
MBase::MBase(1)
于 2012-04-14T17:04:22.153 に答える
1

問題はこれに似ていると思います...基本的に、各オブジェクトにはmBaseクラスの独自のベースオブジェクトがあります...

ダイヤモンドの継承

よろしく、エールヴァルト

于 2012-04-14T17:05:21.980 に答える