Pergunta

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 ?

Foi útil?

Solução

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.

Outras dicas

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top