0

I understand that virtual base class mechanism exists to prevent the "Diamond" problem. But I am curious if the situation is not better handled by re-designing the class hierarchy. Take the case below: copied from here

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

The problem I see with the mechanism as it exists now, is you need to be able to predict that someone is going to come along and inherit from both B and C. So does not mean we are better off tagging every inheritance with virtual?

Community
  • 1
  • 1
Pradyot
  • 2,897
  • 7
  • 41
  • 58
  • Yes we can do that See my question asked on SO http://stackoverflow.com/questions/27457101/sequence-of-constructor-calls-in-multiple-inheritance .But it will be messy and hard to read that code. – Ankur Jan 15 '15 at 13:13
  • 1
    Inheriting from C and D should work fine wrt. A (but not wrt C). Class A is inherited virtually in both chains. There will only be one A sub-object. But yes it's a valid criticism of the mechanism that the decision must be made up at the top level of inheritance. Bertrand Meyer, creator of the Eiffel language, went on at length about it. – Cheers and hth. - Alf Jan 15 '15 at 13:14
  • *virtual inheritance* doesn't have the same cost as *normal inheritance*. – Jarod42 Jan 15 '15 at 13:16
  • also, you may want to read about so-called "mixins", but IIRC almost no library is currently using this approach – quetzalcoatl Jan 15 '15 at 13:19
  • 1
    Maybe complex class hierarchies should be either designed from the ground up or avoided? Meaning if you want a diamond you should design a diamond, not just create one from bits you found laying around. – Galik Jan 15 '15 at 13:30

3 Answers3

3

Virtual inheritance of a class A means that

  • A must be initialized in the most derived class, and
  • access of A things becomes somewhat less efficient (because the A sub-object can be shared between several derived class objects, and thus can be at a dynamic offset in each).

For these reasons virtual inheritance is used with some care.

One good rule of thumb is to use virtual inheritance for interfaces, and not for implementation classes.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
3

You could argue the same point on virtual member functions -- why not make all member functions virtual because if someone comes along and inherits from your class they may like being able to override your member functions. We don't do that because as for virtual base class, virtual member functions have additional costs (in both time/resource overhead and complexity) associated with them.

Paul Evans
  • 27,315
  • 3
  • 37
  • 54
  • Not exactly. As a class designer , you get to specify your intent about inheritance by doing things like pure virtual(abstract) or a virtual destructor(yes , go ahead and inherit). The functions you do not declare virtual, are just inherited and the ones you intend to have overriden are declared virtual. In the virtual base class , the moment you declare a class, someone else can come along and create the "Diamond" – Pradyot Jan 15 '15 at 13:47
0

Virtual inheritance is a must-have feature in all languages that feature multiple inheritance. Although it's possible that all inheritance cases are virtual, but this has:

  • additional costs
  • not always the expected result

It's because virtual inheritance is a special case of inheritance, where the inherited is the directive of direct derivation of the class, not the class itself. In result, every base class that derives another class virtually, provides this virtual base as a direct base class to every next derived class. Of course, if more than one base class provides the same virtual base class, it results in being once derived by the deriving class, but it's because these multiple base classes provide multiple derivation directives, but one class (in contrast to normal inheritance, in which case base classes would provide multiple subobjects of base classes).

The consequence of the fact that it's always a direct base class is the requirement of it being constructed explicitly in every next derived class. Of course, default constructor rules apply, but C++ is not even consequent in this rule - the code where the base class initializes the virtual base is accepted; the only rejected case is when the virtual base is "competitively initialized" in multiple base classes - in this case you have to "resolve the conflict" by providing your construction specification.

Please do not bang me for lame self-promotion, but I've described this topic in more details here:

https://sektorvanskijlen.wordpress.com/2010/12/08/multiple-inheritance-considered-nice

Ethouris
  • 1,791
  • 13
  • 18