Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Virtual Inheritance Confusion

I'm reading about inheritance and I have a major issue that I haven't been able to solve for hours:

Given a class Bar is a class with virtual functions,

class Bar
{
    virtual void Cook();
};

What is the different between:

class Foo : public Bar
{
    virtual void Cook();
};

and

class Foo : public virtual Bar
{
    virtual void Cook();
};

? Hours of Googling and reading came up with lots of information about its uses, but none actually tell me what the difference between the two are, and just confuse me more.

like image 322
Yuki Avatar asked Nov 16 '11 08:11

Yuki


People also ask

What is virtual inheritance explain with example?

There are two vtable pointers, one per inheritance hierarchy that virtually inherits Animal . In this example, one for Mammal and one for WingedAnimal . The object size has therefore increased by two pointers, but now there is only one Animal and no ambiguity.

What happens if we don't use virtual function in inheritance?

If you don't use virtual functions, you don't understand OOP yet. Because the virtual function is intimately bound with the concept of type, and type is at the core of object-oriented programming, there is no analog to the virtual function in a traditional procedural language.

What are the issues with diamond inheritance?

The Diamond Problem is an ambiguity that arises in multiple inheritance when two parent classes inherit from the same grandparent class, and both parent classes are inherited by a single child class.

Should we always use virtual inheritance if yes why if not why not?

The answer is definitely no. The base of an idiomatic answer can be the most fundamental idea of C++: you only pay for what you use. And if you don't need virtual inheritance, you should rather not pay for it. Virtual inheritance is almost never needed.


2 Answers

Functionality wise there is not much difference between the 2 versions. With the case of virtual inheritance, every implementation generally adds a (vptr like) pointer (same as in the case of virtual functions). Which helps to avoid multiple base class copies generated due to multiple inheritance (the diamond inheritance problem)

Also, virtual inheritance delegates the right to call the constructor of its base class. For example,

class Bar;
class Foo : public virtual Bar
class Other : public Foo  // <--- one more level child class

So, now Bar::Bar() will be called directly from Other::Other() and also will be placed at the first place among other base classes.

This delegation feature helps in implementing a final class (in Java) functionality in C++03:

class Final {
  Final() {}
  friend class LastClass;
};

class LastClass : virtual Final {  // <--- 'LastClass' is not derivable
...
};

class Child : public LastClass { // <--- not possible to have object of 'Child'
};
like image 158
iammilind Avatar answered Oct 03 '22 15:10

iammilind


Virtual inheritance is only relevant if classes are to inherit from Foo. If I define the following:

class B {};
class L : virtual public B {};
class R : virtual public B {};
class D : public L, public R {};

Then the final object will only contain one copy of B, shared by both L and R. Without the virtual, an object of type D would contain two copies of B, one in L, and one in R.

There is some argument that all inheritance should be virtual (because in the cases where it makes a difference, that is what you want most of the time). In practice, however, virtual inheritance is expensive, and in most cases, not necessary: in a well designed system, most inheritance will simply be of a concrete class inheriting from one or more "interfaces"; such a concrete class is usually not designed to be derived from itself, so there is no problem. But there are important exceptions: if, for example, you define an interface, and then extensions to the interface, the extensions should inherit virtually from the base interface, since a concrete implementation could want to implement several extensions. Or if you are designing mixins, where certain classes only implement part of the interface, and the final class inherits from several of these classes (one per part of the interface). In the end, the criteron as to whether to inherit virtually or not isn't too difficult:

  • if the inheritance isn't public, it probably shouldn't be virtual (I've never seen an exception), otherwise

  • if the class is not designed to be a base class, there's no need for virtual inheritance, otherwise

  • the inheritance should be virtual.

There are a few exceptions, but the above rules err on the side of safety; it's usually "correct" to inherit virtually even in cases where the virtual inheritance isn't necessary.

One final point: a virtual base must always be initialized by the most derived class, not the class that directly inherits (and declares that the inheritance is virtual). In practice, however, this is a non-issue. If you look at the cases where virtual inheritance makes sense, it is always a case of inheriting from an interface, which will contain no data, and thus have (only) a default constructor. If you find yourself inheriting virtually from classes with constructors which take arguments, it's time to ask some serious questions about the design.

like image 44
James Kanze Avatar answered Oct 03 '22 14:10

James Kanze