The Quantum Physicist The Quantum Physicist -4 years ago 64
C++ Question

Consequences of changing inheritance to virtual?

I'm working on a huge project that I didn't start. My task is to add some additional functionality to what already is there. I'm in a situation where I have to use virtual inheritance because I have a diamond model. The situation is depicted in the following illustration:

Base class
/ \
/ \
My new class A class that was there before (OldClass)
\ /
\ /
\ /
\ /
My other new class


For this to work, both the classes in the middle have to inherit from the base through
public virtual
instead of just
public
. So:

class OldClass: public BaseClass {}


has to become:

class OldClass: public virtual BaseClass {}


Since this project is really huge and I'm working on a small part of it, I don't want to break it by doing this. My adhoc tests worked and the program seems to work fine, but I'm still skeptic.

So my question is: What side effects and consequences should I expect by adding the
virtual
keyword? Is there anything to worry about?

Answer Source

The immediate consequence is that for regular inheritance, derived classes invoke the constructor of the immediate base, while for virtual inheritance, the most derived class (i.e. the one being instantiated directly) does, as this is the only place that would know all the virtual bases.

Compare:

struct A { A(int) { } };
struct B : A { B(int i) : A(i) { } };
struct C : B { C(int i) : B(i) { } };

vs

struct A { A(int) { } };
struct B : virtual A { B(int i) : A(i) { } };
// wrong: struct C : B { C(int i) : B(i) { } };
struct C : B { C(int i) : A(i), B(i) { } }; // correct

Also, the initializer behaviour is different, because the initializer for A in B is ignored if B is not the most derived class:

struct A { A(int i) { cout << 'A' << i; } };
struct B : virtual A { B(int i) : A(i+1) { cout << 'B' << i; } };
struct C : B { C(int i) : A(i+1), B(i+1) { cout << 'C' << i; } };

A a(0);        // prints A0
B b(0);        // prints A1B0
C c(0);        // prints A1B1C0

If you had non-virtual inheritance here (which would force you to remove the A initializer in the C constructor, the third line would output A2B1C0.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download