1

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.

Joan Botella
  • 315
  • 1
  • 2
  • 14
  • You cannot create an object of a class with a [pure virtual function](https://www.geeksforgeeks.org/pure-virtual-functions-and-abstract-classes/) – kesarling He-Him May 21 '20 at 08:22
  • @d4rk4ng31 Yes, I know that by reading the compiler error. But I don't know how to do what I am trying, if it is possible at all. – Joan Botella May 21 '20 at 08:23
  • @d4rk4ng31 Yes, I know, but as the title says, I want to use the derived class through an interface. – Joan Botella May 21 '20 at 08:26
  • 1
    You have to implement `blue()` in `Derived`. [LIVE](https://wandbox.org/permlink/RTNzOugUcVGG4E2v) – songyuanyao May 21 '20 at 08:27
  • I don't want the rest of my application to know which exact concrete class are they using. – Joan Botella May 21 '20 at 08:28
  • @JoanBotella, [If you are interested](https://chat.stackoverflow.com/rooms/214316/chat-room-for-https-stackoverflow-com-questions-61930209-c-using-through-an-int) – kesarling He-Him May 21 '20 at 08:28
  • @songyuanyao I don't want to implement the base code into the derived class. – Joan Botella May 21 '20 at 08:29
  • @JoanBotella You have to implement pure virtual method in derived class; otherwise it'll be abstract class and can't be constructed. `Derived` inherits from `DerivedItf` which inherits from `Base1Itf`; and pure virtual `Base1Itf::blue` doesn't get implemented in this inherit branch. – songyuanyao May 21 '20 at 08:31
  • As I said before, the Derived class should know the least possible about the base classes implementation. Reimplementing their methods it is not ok – Joan Botella May 21 '20 at 08:34
  • In PHP I have done something like this by creating several traits and interfaces for them. The base class uses all the traits and implements an interface that extends all the base interfaces. – Joan Botella May 21 '20 at 08:37
  • Take a look at [diamond problem](https://www.freecodecamp.org/news/multiple-inheritance-in-c-and-the-diamond-problem-7c12a9ddbbec/) in C++ – kesarling He-Him May 21 '20 at 08:44
  • I am updating the question to show you the resulting error. – Joan Botella May 21 '20 at 08:50
  • In fact, it is just the same error. – Joan Botella May 21 '20 at 08:53
  • 2
    Related: [When to use virtual destructors?](https://stackoverflow.com/questions/461203/when-to-use-virtual-destructors) – Phil Brubaker May 21 '20 at 09:09

1 Answers1

0

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

kesarling He-Him
  • 1,944
  • 3
  • 14
  • 39