Search code examples
c++inheritanceinterfacemultiple-inheritance

C++ Using through an interface a class that inherits from several others


I am learning C++ and I am confused about the multiple inheritance and the interface classes.

I want to have a class that inherits from several others. Also, I want to use that derived class through an interface. So I suppose, the derived class should extend the base classes, and the derived interface should extend the base interfaces. I would have done that in other languages, but I think C++ does not work like that.

This is the code I thought should work:

#include <iostream>

using std::cout;
using std::endl;

class
    Base1Itf
{
    public:
        virtual void blue() = 0;
};

class
    Base1Abs
:
    public Base1Itf
{
    public:
        void blue()
        {
            cout << "blue" << endl;
        }
};

class
    DerivedItf
:
    public Base1Itf
{
    public:
        virtual void red() = 0;
};

class
    Derived
:
    public Base1Abs,
    public DerivedItf
{
    public:
        void red()
        {
            cout << "red" << endl;
        }
};

int main()
{
    DerivedItf* d = new Derived();
    d->red();
    d->blue();
    delete d;
    return 0;
}

This is the compiler error I get:

src/test.cpp: In function ‘int main()’:
src/test.cpp:49:30: error: invalid new-expression of abstract class type ‘Derived’
  DerivedItf* d = new Derived();
                              ^
src/test.cpp:35:2: note:   because the following virtual functions are pure within ‘Derived’:
  Derived
  ^~~~~~~
src/test.cpp:10:16: note:       virtual void Base1Itf::blue()
   virtual void blue() = 0;
                ^~~~

In the example only a base class is implemented, but there will be many more.

What I am doing wrong? Thank you.


EDIT

If I remove the Base1Abs inheritance of Base1Itf for avoiding the Diamond Problem, the compiler shows the same error.


Solution

  • This is the well known diamond problem in C++. This is how you solve it:

    #include <iostream>
    
    using std::cout;
    using std::endl;
    
    class Base1Itf {
    public:
        virtual void blue() = 0;
        virtual ~Base1Itf() { }
    };
    
    class Base1Abs : virtual public Base1Itf {
    public:
        void blue() override {
            cout << "blue" << endl;
        }
        virtual ~Base1Abs() { }
    };
    
    class DerivedItf : virtual public Base1Itf {
    public:
        virtual void red() = 0;
        virtual ~DerivedItf() { }
    };
    
    class Derived : public Base1Abs, public DerivedItf {
    public:
        void red() override {
            cout << "red" << endl;
        }
        virtual ~Derived() { }
    };
    
    int main() {
        DerivedItf* d = new Derived();
        d->red();
        d->blue();
        delete d;
        return 0;
    }
    

    It is also recommended to use virtual destructors in inheritance.

    You see, what happens here is that classes Base1Abs and DerivedItf both inherit a copy of blue. Now, when you inherit another class Derived from these 2, that class inherits 2 copies of blue and then the compiler starts wondering which copy is to be called. So, you inherit the 2 classes virtually resulting in only one copy of blue getting inherited