0

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 ?

Rajeshwar
  • 11,179
  • 26
  • 86
  • 158
  • 3
    Yes your understanding is correct. For excellent explanation on this topic, you may read the book "Inside Object C++ Model" by Lippman. – Mantosh Kumar Apr 02 '14 at 19:08
  • possible duplicate of [Why does virtual inheritance need to be specified in the middle of a diamond hierarchy?](http://stackoverflow.com/questions/5166264/why-does-virtual-inheritance-need-to-be-specified-in-the-middle-of-a-diamond-hie) – Shoe Apr 02 '14 at 21:12

1 Answers1

1

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.

pasztorpisti
  • 3,760
  • 1
  • 16
  • 26
  • There's no "racing" involved -- contructors are always invoked strictly in order bottom up and left to right (so constructing D will always involve first constructing A, then B, then C). Also, reasonable implementations will store the A base offset in the vtable and won't use any extra memory per instance. – Chris Dodd Apr 02 '14 at 21:14
  • @ChrisDodd that makes sense, it was quite long ago that I checked this implementation and it actually stored the pointer in the instance. Still even the vtable implementation has its disadvantages, its more lookups in return for more efficient memory usage but it still doesn't make virtual inheritance attractive. On racing I meant that in the implementation I've checked all derived ctors have actually called the ctor of A but only the first call reached its goal. You are right that "racing" may not be the right word here as it sounds as if we had a multithreading related problem here. :-) – pasztorpisti Apr 02 '14 at 21:23
  • Regarding the "hard to tell scenarios where virtual inheritance is really reasonable": look at [this answer](http://stackoverflow.com/questions/21711871/forcing-unqualified-names-to-be-dependent-values/) and [this follow-up question](http://stackoverflow.com/questions/24319185/is-this-interesting-use-pattern-of-virtual-inheritance-for-method-injection-a) I posted. – Oguk Jun 20 '14 at 19:34