In my code, I have a basic diamond pattern:
CommonBase
/ \
/ \
DerivedA DerivedB
\ /
\ /
Joined
It's implemented like this, with the common base class having a default constructor and a constructor taking a parameter:
struct CommonBase {
CommonBase() : CommonBase(0) {}
CommonBase(int val) : value(val) {}
const int value;
};
struct DerivedA : public virtual CommonBase {
void printValue() {
std::cout << "The value is " << value << "\n";
}
};
struct DerivedB : public virtual CommonBase {
void printValueTimes2() {
std::cout << "value * 2 is " << value * 2 << "\n";
}
};
struct Joined : public DerivedA,
public DerivedB {
Joined(int val) : CommonBase(val) {
std::cout << "Constructor value is " << val << "\n";
std::cout << "Actual value is " << value << "\n";
}
};
The Joined
class initializes the virtual base using the constructor that takes a parameter, and everything works as expected.
However, when I derive a class from the Joined
class, something strange happens - the CommonBase
's default constructor is called unless I explicitly initialize CommonBase
in the derived classes constructor as well.
This is demonstrated using this code:
struct JoinedDerivedA : public Joined {
JoinedDerivedA() : Joined(99) {
printValue();
}
};
struct JoinedDerivedB : public Joined {
JoinedDerivedB() : Joined(99), CommonBase(99) {
printValue();
}
};
int main() {
std::cout << "======= Joined =======\n";
Joined j(99);
j.printValue();
std::cout << "\n=== JoinedDerivedA ===\n";
JoinedDerivedA a;
std::cout << "\n=== JoinedDerivedB ===\n";
JoinedDerivedB b;
return 0;
}
The output of this code is
======= Joined =======
Constructor value is 99
Actual value is 99
The value is 99
=== JoinedDerivedA ===
Constructor value is 99
Actual value is 0 // <-- unexpected behaviour
The value is 0
=== JoinedDerivedB ===
Constructor value is 99
Actual value is 99
The value is 99
Why is this the case? Is it possible to not have to explicitly initialize the common base class in derived classes again?
Here's the code on ideone, so you can run it yourself: https://ideone.com/Ie94kb