【问题标题】:Diamond issue when trying to resolve it using virtual inheritance尝试使用虚拟继承解决钻石问题
【发布时间】:2025-11-24 10:10:01
【问题描述】:

我是 C++ 新手,在解决钻石问题时我很烂: 这里是代码:

#include <iostream>

using namespace std;

// Base class
class Base 
{
   public:
      virtual void getArea()
      { 
         cout << "Called by Base\n"; 
      }
};

// Derived class
class Rectangle: public virtual Base
{
   public:
      void getArea()
      { 
         cout << "Called by Rectangle\n";
      }
};

// Derived class
class Square: public virtual Base
{
   public:
      void getArea()
      { 
         cout << "Called by Square\n";
      }
};

// Derived class
class Triangle: public Rectangle, Square
{
   public:
      void blabla(){}
};

int main(void)
{
    Triangle Tri;
    Tri.getArea();

    return 0;
}

我得到了 g++ 错误:

main.cpp:36:7: error: no unique final overrider for ‘virtual void Base::getArea()’ in ‘Triangle’
 class Triangle: public Rectangle, Square
       ^
main.cpp: In function ‘int main()’:
main.cpp:45:6: error: request for member ‘getArea’ is ambiguous
  Tri.getArea();
      ^
main.cpp:29:12: note: candidates are: virtual void Square::getArea()
       void getArea()
            ^
main.cpp:19:12: note:                 virtual void Rectangle::getArea()
       void getArea()

我在互联网上发现虚拟继承解决了这个问题那么我的错误是什么。

提前致谢

【问题讨论】:

    标签: c++ inheritance diamond-problem


    【解决方案1】:

    作为编译器思考:你应该调用什么方法?

    你有一个既是正方形又是矩形的三角形,你要问的是面积。您的三角形应该选择使用Rectangle.getArea() 还是Square.getArea()

    编译器无法知道。这里的一个解决方案是覆盖 getArea() 方法,例如:

    class Triangle: public Rectangle, Square
    {
       public:
          void blabla(){}
          void getArea()
          { 
             Square::getArea; //I'm a square
             Rectange::getArea; //I'm a rectangle
          }
    };
    

    即使没有类 Base 也会触发此问题。使用菱形继承的示例如下所示:

    class Base
    {
       protected:
          int x;
    };
    
    
    class Derived1: virtual public Base
    {
       //some stuff
    };
    
    
    class Derived2: virtual public Base
    {
       //some stuff
    };
    
    
    class Join: public Derived1, public Derived2
    {
       int getX(){
         return x;
       }
    };
    

    在这里,使用虚拟继承允许我们在 Join 实例中只有一个 Base 类的实例,而不是 2 个没有并且应该选择 x 的错误。

    【讨论】:

      【解决方案2】:

      您的问题是您在同一继承级别上有两个不同的类,它们提供了对虚拟方法的不同覆盖。编译器不知道哪个应该优先,因此您需要提供自己的覆盖并做任何您想做的事情(调用其中一个函数,两者都调用,或者滚动您自己的实现)。

      【讨论】:

        最近更新 更多