Pergunta

I understand and have read enough about the diamond problem which is solved by virtual inheritance. My question here is

"What does placing virtual next to a base class that you would be inheriting from actually mean"

class A { public: void Foo() {} };
class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};

I wanted to know if my understanding is correct. In the statement

  class D : public B, public C {}

The compiler will go over first base class B and notice that its inheriting virtually from class A. The compiler will check if instance of class A is present if not it will create an instance of A that is derived by B . The compiler will then go over class C and notice that it inherits virtually from class A. However since its being inherited virtually by C and an instance of A is already present it wont include a new instance. Thus solving the diamond problem. Is this understanding correct ?

Foi útil?

Solução

Yes, your understanding is correct but it would be hard to tell scenarios where virtual inheritance is really reasonable and even in those cases the problem can usually be solved with something else that is more simple.

In your case your D instance will be a composition of a C, a B and a single A instance. Since both A and B can make part in different scenarios with different compositions where A is inherited virtually by many classes (maybe even more classes than A and B) it is not clear how to lay out for example the building blocks of a D instance in memory. For this reason the code compiled for classes B and C usually make use of utility pointers or offsets (1 pointer per instance, one for B and one for C) that point to the A instance that is shared by the code of different classes that inherit virtually from class A. This takes up extra space in your D instance and makes your code less effective by playing around with those pointers.

Another ugly implementation detail is that in case of your D class when you create/initialize an instance of D both your B and C instances are "racing" for calling the constructor of class A from their constuctors. For this reason your D instance will also contain a bool variable that indicates whether someone has already called the ctor of A from its constructor. One of the ctors of B and C will win and set this bool variable tot true so the following attempts coming from the ctors of other "virtual descendants" simply bail out after checking that particular bool value.

Virtual inheritance is simply ugly and avoid whenever possible.

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