Понимание виртуальных базовых классов и вызовов конструктора
Я немного озадачен тем, как работают виртуальные базовые классы. В частности, мне было интересно, как вызывается конструктор базового класса. Я написал пример, чтобы понять это:
#include <cstdio>
#include <string>
using std::string;
struct A{
string s;
A() {}
A(string t): s(t) {}
};
struct B: virtual public A{
B(): A("B"){}
};
struct C: virtual public A {};
struct D: public B, public C {};
struct E: public C, public B {};
struct F: public B {};
int main(){
D d;
printf("\"%s\"\n",d.s.c_str());
E e;
printf("\"%s\"\n",e.s.c_str());
F f;
printf("\"%s\"\n",f.s.c_str());
B b;
printf("\"%s\"\n",b.s.c_str());
}
Какие выводы
""
""
""
"B"
Я не был уверен, что произойдет в первых двух случаях, но для третьего, по крайней мере, я ожидал, что результат будет "B". Так что теперь я просто запутался. Каковы правила для понимания, как вызывается конструктор A?
2 ответа
Всегда есть только один вызов конструктора и всегда фактический конкретный класс, который вы создаете. Вы несете ответственность за обеспечение каждого производного класса конструктором, который вызывает конструкторы базовых классов в случае необходимости, как вы это делали в B
конструктор.
Обновление: извините за то, что упустили ваш главный вопрос! Благодаря ildjarn.
Тем не менее, ваш B
наследует практически от A
, Согласно стандарту (10.1.4 в FIDS), "для каждого отдельного базового класса, который указан виртуальный, наиболее производный объект должен содержать один подобъект базового класса этого типа". В вашем случае это означает, что при построении базы ваш класс F
немедленно звонит A
конструктор по умолчанию, а не B
"S.
Виртуальные базовые классы всегда создаются самым производным классом.