-2

The virtual inheritance in C++ is an useful way to prevent the diamond issue. However, I can't seem to make it work properly in each and every case.

This is going to be very hard to explain but I hope I'll manage. Let's present the problem:

A inherits B. And A is the base class of a class set called C and another class set called D.

The problem is that the C set of class have common features focusing around B.

What I would like to do, but isn't possible, is a class E that virtually inherits B, and which is inherited by C. Problem is:

In this case, A doesn't virtually inherits B. So it doesn't work.

If A was to virtually inherit B, then I would need to use B's constructor in every classes of D.

Conclusion: in every case there is duplicated code. How may I get out of this issue without any duplicated code ?

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
Michael
  • 1,357
  • 3
  • 15
  • 24
  • give a short example of what does not work. – Walter Aug 10 '13 at 18:29
  • Given what you've told us so far, those two options are your only options - have two copies of B in E, or put up with explicitly constructing B everywhere. There's probably a better design, but without background on what the classes are and why the inheritance tree is like that, no one's going to be able to help. – je4d Aug 10 '13 at 18:41

2 Answers2

1

Okay so you are saying that you have:

                             B
                             +
                             |
                             v
                             A
                             +
                        +----+----+
                        v         v
                        C         D

And all of these are non-virtual inheritance and then you have class E that virtualy inherits B and C also inherits it so a complete diagram would be:

                +-----------+B
                |            +
                |            |
                v            v
                E            A
                +            +
                +---+---+----+----+
                    v             v
                    C             D                                  

With the exception that B is virtualy inherited by E.

The solution is simple you should make A also virtually inherit B, however I gathered from your question that you can not modify A. Your next option is to make C inherit A or E and have an instance of the other this is called delegation. An alternative you can provide a common interface and allow polymorphism you might want to make an interface (pure virtual class) that has all the function in E that C uses and then make C and E derive that interface. E would implement the virtual functions from the interface and C would implement it as function calls to E's implementation. Alternatively (not recommended) you can live with the diamond of death if it is not problematic for you, however determining that is tricky and I don't recommend this it's a terrible idea.

A. H.
  • 942
  • 10
  • 20
  • You should reverse the inheritance arrows so it follows the uml convention. The arrow should point to the class being inherited from rather than the class doing the inheriting. – greatwolf Aug 10 '13 at 23:02
  • Thank you ! The third option did the trick: it allows me to keep the API as it currently is while making the code dry. There's a little caveat here: virtual methods from the interface that are implemented in A rather than B cannot be solved for classes inheriting E (it's ambiguous). I'll work around that anyway, this is still the best possible option by far. – Michael Aug 11 '13 at 10:02
1

Split B into an interface part IB (an abstract base class, no data members) and an implementation part Bimpl. Multiply-inherit only IB. Since IB has no data members, there's no need for a non-default constructor, so you don't have to repeat it everywhere.

For each class C in the hierarchy that becomes abstract because of this change, create Cimpl that inherits from both C and Bimpl. Never inherit from Cimpl. Non-default constructor(s) of Bimpl, formerly of B, are only called in C.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243