0

Can't get my program compile. For historical reason I have a bit "complicated" hierarchy of the classes in my application. And now I faced with another problem: it won't compile because of this hierarchy. My project is too big to show it here, but below you can see the example that demonstrates the problem. Is there is a simple and elegant way to fix it? Every interface/class has really big amount of methods. Thanks in advance.

struct ITest
{
    virtual ~ITest() {}
    virtual void a() = 0;
    // and many other methods
};

struct Test1 : public ITest
{
    virtual ~Test1() {}
    virtual void a() override {}
    // and many other methods overrides from ITest
    // plus a lot of other logic
};

struct ExtendedTest1 : public Test1
{
    virtual ~ExtendedTest1() {}
    // a lot of some other stuff
};

struct ITest2 : public ITest
{
    virtual ~ITest2(){}
    // and big count of the its methods and logic
};

struct MainClass : public ExtendedTest1, public ITest2
{
     virtual ~MainClass(){}
     // a lot of logic
};

int main()
{
    MainClass mainClassObj;
    return 0;
}

And the errors:

main.cpp: In function ‘int main()’:
main.cpp:36:15: error: cannot declare variable ‘mainClassObj’ to be of abstract type ‘MainClass’
     MainClass mainClassObj;
               ^~~~~~~~~~~~
main.cpp:28:8: note:   because the following virtual functions are pure within ‘MainClass’:
 struct MainClass : public ExtendedTest1, public ITest2
        ^~~~~~~~~
main.cpp:4:18: note:    virtual void ITest::a()
     virtual void a() = 0;
                  ^

Do not judge strictly :)

UPD: before asking this question I really tried virtual inheritance to solve my problem but it didn't work. So after suggestion to try it again, it works) So, replacing these lines solved my problem:

struct Test1 : public ITest  --->  struct Test1 : virtual public ITest
struct ITest2 : public ITest ---> struct ITest2 : virtual public ITest

I know, we must avoid virtual inheritance, but we can't 'cause of historical reason and very big amount of code

Thanks everybody for help!

user2123079
  • 656
  • 8
  • 29
  • 4
    Perhaps you need [virtual iheritance](https://en.wikipedia.org/wiki/Virtual_inheritance)? –  Oct 02 '19 at 20:24
  • @Chipster, can you please rewrite your comment to answer? I want to mark it as "answer". Indeed, virtual inheritance solved my problem. I actually tried it, but I did it in a wrong way. And after few minutes of the fresh air I did it :) – user2123079 Oct 02 '19 at 20:37
  • I wrote it as an answer for you. –  Oct 02 '19 at 20:45

3 Answers3

2

The function a is pure virtual, as in it's not implemented anywhere in the hierarchy MainClass -> ITest2 -> ITest.

See the "deadly diamond of death" problem of multi-inheritance for more discussion.

The easiest solution is to avoid doing this type of inheritance if you're not exactly sure of what you're doing. Second, you may consider implementing a in MainClass which forwards the arguments to a qualified call to a in Test1 if that's what you were expecting.

Braaedy
  • 540
  • 1
  • 5
  • 16
2

MainClass has two base classes, both of which are derived (directly or indirectly) from ITest. So there are two ITest subobjects in MainClass. One of these base classes provides an override for a, but the other (ITest2) does not. The implementation in Test1 is not accessible from ITest2. So MainClass will need to provide an implementation.

If you want Test1::a to be called even from the ITest2 subobject, you can have MainClass redirect those calls to Test1::a.

struct MainClass: public ExtendedTest1, public ITest2
{
    // ...
    void a() override { ExtendedTest1::a(); }
};

Another possibility is virtual inheritance.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
2

You need Virtual Inheritance.

Virtual inheritance can get rid of redundant functions:

Instead, if classes B and C inherit virtually from class A, then objects of class D will contain only one set of the member variables from class A.

If you inherit virtually, you will get rid of your duplicate abstract function.