NPS
NPS

Reputation: 6355

How does virtual inheritance actually work?

I know about the diamond problem but the thing is - when I google "virtual inheritance" the results mention only the diamond problem. I want to know how it works in general and how is it different from normal inheritance.

I know when a class (normally) inherits from another class it simply contains all its members (fields and methods, leaving aside the access levels). Some of them may be overridden or hidden by new members but they're still there. Inheritance also defines certain relationships between classes in hierarchy which affects casting and polymorphism.

Now how is virtual inheritance different? For instance:

class A
{
    public:
    int a;
    int b;
    void fun(int x)
    {}
    void gun(int x)
    {}
};

class B : public A
{
    public:
    int a;
    int c;
    void fun(int x)
    {}
    void hun(int x)
    {}
};

class C : virtual public A
{
    public:
    int a;
    int c;
    void fun(int x)
    {}
    void hun(int x)
    {}
};

What are the differences between B and C? Are there any other differences that my example doesn't exploit? What does the standard say? Also, if there's a difference between C++03 and C++11 please mention it.

Upvotes: 1

Views: 582

Answers (1)

Mike Seymour
Mike Seymour

Reputation: 254721

With a single level of inheritance, there's no difference in behaviour.

The difference is when inheriting from multiple base classes, which themselves have a common base class:

struct A {};
struct B : virtual A {};
struct C : virtual A {};
struct D : B,C {};

In this example, with virtual inheritance, D contains just one A sub-object, which its B and C subobjects share; this is the "diamond" pattern:

    A
   / \
   B C
   \ /
    D

Without virtual inheritance, it would contain two A sub-objects, and no "diamond":

   A A
   | |
   B C
   \ /
    D

With or without multiple inheritance, there's still a difference if you have more than one level of inheritance: a virtual base class must be initialised by the most derived class, not by its immediate derived class. This is to avoid the ambiguity in the case of multiple inheritance, where (in the example above) both B and C would otherwise be responsible for initialising the shared A.

Upvotes: 5

Related Questions