I stumbled upon this code example:
#include <iostream>
using namespace std;
class A {
int x;
public:
A() { x = 1; cout << "A"; }
};
class B : virtual public A {
int y;
public:
B() { y = 2; cout << "B"; }
};
class C : virtual public B, virtual public A {
int z;
public:
C() { z = 3; cout <<"C"; }
};
class D : public A, public B, public C {
int t;
public:
D() { t = 4; cout << "D"; }
};
int main()
{
D d;
return 0;
}
This code prints ABABCD
and I have no idea why. I thought it would print A
for D : public A
, then AB
for D : public B
, then ABC
for D : public C
, and then D
, but it seems A
is only printed twice. How does this work?
The order of construction of the bases is (ignoring virtual bases) left to right as they are typed in the inheritance relationship. Once you add virtual bases, those are initialized first (before any non-virtual base) in a depth-first left-to-right manner.
Now this should explain the output.
D : A, B, C
A has no virtual bases, B has a virtual A base, so that is the first initialized: "A". Then C has a virtual B base, so that is the next one being initialized. At this point the A virtual subobject has already been initialized, so only the B constructor is evaluated "AB". At this point all virtual bases have been constructed and the non-virtual bases are constructed, first A, then B, then C, then the complete type D, yielding "ABABCD". The virtual sub objects have all been constructed, so they don't get constructed again.
Some things to keep in mind. A virtual base is only shared with other subobjects that are willing to share it (i.e. have it as a virtual base). There is no limit as of how many times a virtual base can be shared within a complete object (i.e. the A virtual base is shared multiple times, including from different B subobjects)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With