У меня есть следующая проблема:
struct A1 {
A1() { std::cout << "A1, "; }
};
struct A2 {
A2() { std::cout << "A2, "; }
};
struct AA1 : virtual A1, A2 {
AA1() { std::cout << "AA1, "; }
};
struct AA2 : A1, virtual A2 {
AA2(){ std::cout << "AA2, "; }
};
struct B : AA1, virtual AA2 {
B() { std::cout << "B "; }
};
int main() {
B b;
}
Когда вы запускаете этот код, ответ:
A1 A2 A1 AA2 A2 AA1 B
Я хочу понять, где первый A1
создано.
Я знаю правило, что виртуальные классы вызываются раньше, чем не виртуальные классы, но первый A1 — это проблема, которая беспокоит меня.
Первый A1
результаты инициализации (виртуальной) базы (не виртуальной) базы AA1
из B
,
Все виртуальные базы B
инициализируются в первую очередь, и они, по порядку, A1
, A2
а также AA2
, (Инициализация AA2
результаты в выводе A1 AA2
.) Затем приходят прямые основания, из которых есть только одна, AA1
(чья инициализация печатает A2 AA1
) и наконец сам класс, печать B
, Сначала идут все виртуальные базы, а затем только оставшиеся не виртуальные.
B
имеет три виртуальных базовых класса: A1
, A2
а также AA2
и, в соответствии с их порядком появления, он будет инициализировать их в этом порядке.
Первый A1
а также A2
вы видите инициализацию виртуальной базы A1
а также A2
, но последняя виртуальная база AA2
имеет не виртуальную базу A1
, так что перед построением AA2
вам нужно будет построить другой A1
вот почему у вас есть другой A1
до AA2
,
Вы можете визуализировать это, запустив следующий фрагмент:
#include <iostream>
struct A1 {
A1(const char *s) { std::cout << "A1(" << s << ")\n"; }
};
struct A2 {
A2(const char *s) { std::cout << "A2(" << s << ")\n"; }
};
struct AA1 : virtual A1, A2 {
AA1(const char *s) : A1("AA1"), A2("AA1") { std::cout << "AA1(" << s << ")\n"; }
};
struct AA2 : A1, virtual A2 {
AA2(const char *s) : A1("AA2"), A2("AA2") { std::cout << "AA2(" << s << ")\n"; }
};
struct B : AA1, virtual AA2 {
B() : A1("B"), A2("B"), AA1("B"), AA2("B") { std::cout << "B()\n"; }
};
int main() {
B b;
}
Это выведет:
A1(B)
A2(B)
A1(AA2)
AA2(B)
A2(AA1)
AA1(B)
B()
Вы также можете заметить, что этот код предупреждает вас, потому что:
A1
до A2
в AA2
конструктор, но A2
будет инициализирован раньше A1
(потому что это виртуальная база и A1
не является).AA1
до AA2
в B
конструктор, но AA2
будет инициализирован первым (по той же причине).