В моем коде у меня есть базовый ромбовидный шаблон:
CommonBase
/ \
/ \
DerivedA DerivedB
\ /
\ /
Joined
Он реализован так: общий базовый класс имеет конструктор по умолчанию и конструктор, принимающий параметр:
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";
}
};
Класс Joined
инициализирует виртуальную базу с помощью конструктора, который принимает параметр, и все работает как положено.
Однако, когда я наследую класс от класса Joined
, происходит нечто странное - конструктор по умолчанию CommonBase
называется , если только я явно не инициализирую CommonBase
в конструкторе производных классов.
Это демонстрируется с помощью этого кода:
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;
}
Вывод этого кода:
======= 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
Почему это так? Можно ли не выполнять явную инициализацию общего базового класса в производных классах снова?
Вот код для ideone, так что вы можете запустить его самостоятельно: https://ideone.com/Ie94kb