为什么这种钻石图案存在歧义?

Moe*_*oeb 7 c++ diamond-problem

#include <iostream>
using namespace std;

class A             { public: void eat(){ cout<<"A";} };
class B: public A   { public: void eat(){ cout<<"B";} };
class C: public A   { public: void eat(){ cout<<"C";} };
class D: public B,C { public: void eat(){ cout<<"D";} };

int main(){
    A *a = new D();
    a->eat();
}
Run Code Online (Sandbox Code Playgroud)

我不确定这是否称为钻石问题,但为什么这不起作用?

我已经给出了认定中进行eat()D.因此,它不需要使用任何B一个或C副本(因此,应该没有问题).

当我说,a->eat()(记住eat()不是虚拟的),只有一个可以eat()调用,即A.

为什么然后,我是否收到此错误:

'A'是'D'的模糊基础


究竟A *a = new D();对编译器意味着什么?

为什么我使用时不会出现同样的问题D *d = new D();

小智 6

菱形在D对象中产生两个A实例,并且你所指的是一个模糊的 - 你需要使用虚拟继承来解决这个问题:

class B: virtual public A   { public: void eat(){ cout<<"B";} };
class C: virtual public A   { public: void eat(){ cout<<"C";} };
Run Code Online (Sandbox Code Playgroud)

假设你实际上只想要一个实例.我还假设你的意思是:

class D: public B, public C { public: void eat(){ cout<<"D";} };
Run Code Online (Sandbox Code Playgroud)

  • @cambr这与eat()函数无关 - 尝试注释掉它的调用. (2认同)

Joh*_*itb 2

想象一个稍微不同的场景

class A             { protected: int a; public: void eat(){ a++; cout<<a;} };
class B: public A   { public: void eat(){ cout<<a;} };
class C: public A   { public: void eat(){ cout<<a;} };
class D: public B,C { public: void eat(){ cout<<"D";} };

int main(){
    A *a = new D();
    a->eat();
}
Run Code Online (Sandbox Code Playgroud)

如果这可行,它会增加ainBain吗C?这就是为什么它是暧昧的。对于两个子对象(其中一个由子对象包含,另一个由子对象包含),指针this和任何非静态数据成员都是不同的。尝试像这样更改您的代码,它会起作用(因为它编译并打印“A”)ABC

class A             { public: void eat(){ cout<<"A";} };
class B: public A   { public: void eat(){ cout<<"B";} };
class C: public A   { public: void eat(){ cout<<"C";} };
class D: public B, public C { public: void eat(){ cout<<"D";} };

int main(){
    A *a = static_cast<B*>(new D());
      // A *a = static_cast<C*>(new D());
    a->eat();
}
Run Code Online (Sandbox Code Playgroud)

这将分别调用eat和的A子对象。BC