C ++中的多重继承,它看起来像钻石,但事实并非如此

时间:2013-09-17 17:05:17

标签: c++ inheritance multiple-inheritance diamond-problem

C ++中的多重继承问题:

它看起来像钻石问题,但事实并非如此。它不能通过添加虚拟继承来解决。

struct A {
   virtual void f() { cout << "A::f()" << endl; };
};

struct B : public virtual A {
   void f() { cout << "B::f()" << endl;};
};

struct C :  public virtual A {
  void f() { cout << "C::f()" << endl;};
};

struct D : B, C { };

int main() {
  D d;

  B* bp = &d;
  A* ap = bp;
  D* dp = &d;

  ap->f();
  dp->f(); // compile error here because D has two candidates f() to override. 
        // error: request for member f is ambiguous
        // error: candidates are: virtual void C::f()
        // error:                 virtual void B::f()

  }

我是对的吗?

4 个答案:

答案 0 :(得分:4)

  

它看起来像钻石问题,但事实并非如此。

是的;这是经典的“钻石”图案。也许你的意思是,这个问题不是由钻石的存在引起的?这当然是正确的,所以我想知道为什么你在这个问题中包含了那个红鲱鱼。你会从一个更简单的例子中得到同样的问题:

struct B {
   virtual void f() { cout << "B::f()" << endl;};
};

struct C {
   virtual void f() { cout << "C::f()" << endl;};
};

struct D : B, C { };
  

这里编译错误,因为D有两个候选f()要覆盖。

不,错误是因为D没有覆盖它们,所以函数调用有两个候选者。虚函数在两个直接基类中都被重写,但在派生类中没有,因此没有唯一的最终覆盖。

您需要决定D::f()应该做什么,并相应地实施。

答案 1 :(得分:0)

错误不在您指定的行中,而是在D的类定义中。该定义完全不正确,因为虚函数没有唯一的最终覆盖。

答案 2 :(得分:0)

你有两个具有相同签名的函数来自B类和C类,因此成员函数f()是不明确的(你已经指出过)。

答案 3 :(得分:-1)

也许ap = bp会隐式转换,因此ap-&gt; f()将被识别为B :: f,但dp有两个f()可供选择。

编辑:任何人都可以解释为什么ap-&gt; f()不会抛出错误但是dp-&gt; f()会不会?