4
struct B { int i; };
struct D1 : virtual B {};
struct D2 : B {};  // <-- not virtual
struct DD : D1, D2 {};

上記のコーディングを行っても、コンパイラは次のD2ことも要求しますvirtual

DD d;
d.i = 0; // error: request for member `i' is ambiguous

私が理解していないのは、(経由で)コンパイラBにプロンプ​​トを表示virtualした後、なぜそれがまだ曖昧なのかということです。DDD1i

(私の記憶が正しければ、古いVC++(2006年)は、単一virtual継承だけでこれを理解するのに十分な能力がありました)

4

3 に答える 3

7

B は DD に関しては仮想ではありません。D1 に関しては仮想です。D2 が作成された時点では、B の完全なコピーが含まれています。そのため、DD には B の 2 つの実装があります。そして、 のコピーを 2 つ持っiていて、それを使用するのは確かにあいまいです。

D2 も B のコピーを含む代わりに仮想継承を使用していた場合、D1 も指している B のインスタンスへのポインターが含まれ、DD には B のインスタンスが 1 つだけ含まれていたことになります。

私はメモリレイアウトを説明しようとします.これがうまくいくことを願っています...:

あなたの場合、1つの仮想継承と1つの非仮想継承があります-

|    D1    |   D2 + B |    B    |
+--+-------+----------+---------+
 |   vptr to B           ^
 +-----------------------|

D1 と D2 の両方を仮想的に継承させる -

|   D1   |   D2   |   B   |
+--+-----+---+----+-------+
 |         |         ^
 +---------+---------|
于 2011-07-08T06:21:34.320 に答える
2

この場合、標準ではd.iあいまいである必要があります。ISO / IEC 14882:2003セクション10.1.6は、特定のタイプの仮想および非仮想基本クラスを持つクラスを対象としています。

于 2011-07-08T06:44:12.550 に答える
2

ダイヤモンド問題を読む必要があります。CPPのアプローチの見出しの下で、あなたのケースが明確に言及されており、あなたの観察はそこで説明されているものと一致しています。

于 2011-07-08T06:11:19.683 に答える