为什么单个虚拟继承不足以解决可怕的钻石问题?

iam*_*ind 4 c++ virtual-inheritance diamond-problem language-lawyer

struct B { int i; };
struct D1 : virtual B {};
struct D2 : B {};  // <-- not virtual
struct DD : D1, D2 {};
Run Code Online (Sandbox Code Playgroud)

上面已经编码,还是编译器的需求D2也将virtual:

DD d;
d.i = 0; // error: request for member `i' is ambiguous
Run Code Online (Sandbox Code Playgroud)

我不明白的是,一旦你提示编译器Bvirtual关于DD(via D1)那么为什么它仍然i是模棱两可的?

(如果我的内存服务正确,那么旧的VC++(2006年)就足以用单virtual继承来证明这一点)

era*_*ran 7

B对于DD不是虚拟的 - 它相对于D1是虚拟的.在创建D2时,它包含B的完整副本.所以现在DD有两个B实现:一个作为D2的一部分,一个作为结尾(由D1指向).有两份副本i,使用它确实含糊不清.

如果D2也使用虚拟继承,而不是包含B的副本,它将包含指向D1也指向的B实例的指针,而DD将只包含一个B实例.

我将尝试说明内存布局,希望这是正确的......:

你的情况,一个虚拟继承和一个非虚拟 -

|    D1    |   D2 + B |    B    |
+--+-------+----------+---------+
 |   vptr to B           ^
 +-----------------------|
Run Code Online (Sandbox Code Playgroud)

让D1和D2都虚拟地继承 -

|   D1   |   D2   |   B   |
+--+-----+---+----+-------+
 |         |         ^
 +---------+---------|
Run Code Online (Sandbox Code Playgroud)