Search code examples
c++inheritancediamond-problem

Diamond issue when trying to resolve it using virtual inheritance


I am new in C++ and I am suck when resolving the diamond problem: here the code:

#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;
}

I got the g++ errors:

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()

I found on Internet that virtual inheritance resolves the problem So what is my mistake(s).

thanks in advance


Solution

  • Think as a compiler: what method should you call ?

    You have a triangle that is both a Square and a Rectangle and you are asking is area. Should your triangle choose to use Rectangle.getArea() or Square.getArea() ?

    The compiler cannot know. A solution here is to overide the getArea() method, for instance:

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

    This problem would be trigger even is there was no class Base. An exemple on use of diamond inheritance would look like this:

    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;
       }
    };
    

    In here, using virtual inheritance allows us to only have one instance of the Base class in the Join instance, instead of 2 without and an error on which x should be selected.