1

Java のバックグラウンドから来て、 http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problemで詳細に説明されているように、多重継承がオーバーライドの問題を引き起こす可能性があるダイヤモンドの問題に遭遇したことはありません。

しかし、この問題が発生した場合、C++ ランタイムは文句を言うのでしょうか、それともスーパー クラス メソッドのどの実装が呼び出されるかはランダムなのでしょうか?

記事の「緩和」の部分を読みましたが、完全には理解できませんでした。

4

2 に答える 2

2

コンパイラは、あいまいさを診断することによって、ダイアモンドの問題が発生しているプログラムを見つけます。

解決策の 1 つは、あいまいさを取り除くことです。これは、明示的な名前修飾を使用してメンバーを参照するときに実行できます。

struct B {
    int bar;
};

struct D1 : B {};
struct D2 : B {};

struct E : D1, D2 {};

int main() {
    E e;
    e.D1::bar = 1; // explicitly set D1::bar, not D2::bar.
}

または、次のようにベース サブオブジェクトにアクセスする場合: B *b = new E;D1 または D2 のベース サブオブジェクトが必要かどうかはあいまいです。これらの中間型のいずれかへの明示的なキャストを使用すると、あいまいさが解決されます。

B *b = static_cast<D2*>(new E);

また、B* から E* へのダウンキャストは静的に行うことができないことに注意してください。コンパイラは、どの B が指されているかを認識していないため、ポインターを調整して E に戻す方法を静的に認識していません。ここで、dynamic_cast が必要になります。

E *e = new E;
B *b1 = static_cast<D1*>(e);
B *b2 = static_cast<D2*>(e);
assert(b1 != b2);
assert(dynamic_cast<E*>(b1) == dynamic_cast<E*>(b2));
assert(e == dynamic_cast<E*>(b1));

もう 1 つの解決策は、仮想継承の問題を回避して、同じ型の複数の基本サブオブジェクトを回避することです。

struct B {
    virtual void foo() = 0;
    virtual ~B() = default;
    int bar;
};

struct D1 : virtual B {};
struct D2 : virtual B {};

struct E : D1, D2 {
    virtual void foo() override {
        bar = 1; // no ambiguity because there's only a single B base sub-object
    }
};
于 2012-10-16T22:23:34.993 に答える
1

エラーはコンパイラによってキャッチされます。http://www.parashift.com/c%2B%2B-faq-lite/mi-diamond.htmlで提供される例があります

class Base {
public:
protected:
  int data_;
};

class Der1 : public Base {  };

class Der2 : public Base {  };

class Join : public Der1, public Der2 {
public:
  void method()
  {
      data_ = 1; //g++ error: reference to ‘data_’ is ambiguous
  }
};

int main()
{
  Join* j = new Join();
  Base* b = j; //g++ error: ‘Base’ is an ambiguous base of ‘Join’
}
于 2012-10-16T21:33:17.293 に答える