#include <iostream>
using namespace std;
struct A{
A() {cout << "A" << endl;}
A(int a) {cout << "A+" << endl;}
};
struct B : virtual A{
B() : A(1) {cout << "B" << endl;}
};
struct C : virtual A{
C() : A(1) {cout << "C" << endl;}
};
struct D : virtual A{
D() : A() {cout << "D" << endl;}
};
struct E : B, virtual C, D{
E(){cout << "E" << endl;}
};
struct F : D, virtual C{
F(){cout << "F" << endl;}
};
struct G : E, F{
G() {cout << "G" << endl;}
};
int main(){
G g;
return 0;
}
Программа печатает:
A
C
B
D
E
D
F
G
Я хотел бы знать, какие правила я должен использовать, чтобы определить, в каком порядке вызываться конструкторы. Благодарю.
Вы должны следовать правилам, приведенным в стандарте C ++:
[C++11: 12.6.2/10]:
В не делегирующем конструкторе инициализация происходит в следующем порядке:
- Во-первых, и только для конструктора самого производного класса (1.8), виртуальные базовые классы инициализируются в том порядке, в котором они отображаются при обходе слева направо по глубине направленного ациклического графа базовых классов, где «слева-направо» направо »- это порядок появления базовых классов в производном классе базовый спецификатор-лист.
- Затем прямые базовые классы инициализируются в порядке объявления, как они появляются в списке базовых спецификаторов (независимо от порядка MEM-Инициализаторы).
- Затем не статические члены данных инициализируются в порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка MEM-Инициализаторы).
- Наконец, компаунд-заявление тела конструктора выполнен.
[ Заметка: Порядок объявления должен гарантировать, что базовые и членские подобъекты уничтожаются в обратном порядке инициализации. —Конечная записка]
Виртуальные базовые подобъекты создаются вначале самым производным классом перед любыми другими базами. Это единственный способ, который имеет смысл, поскольку отношение виртуальных баз к самому производному объекту неизвестно до конструирования объекта, во время выполнения (следовательно, «виртуальное»). Все промежуточные инициализаторы для виртуальных баз игнорируются.
Итак, каковы ваши виртуальные базы? G
происходит от E
а также F
, E
происходит практически от C
что, в свою очередь, вытекает практически из A
, так A
, C
являются первыми. Следующий, F
не добавляет никаких дополнительных виртуальных баз. Следующий, E
имеет не виртуальные базы B
а также D
в том порядке, в котором строятся следующие, а затем E
завершено. Потом приходит F
не виртуальная база D
, а также F
завершено. В заключение, G
завершено.
В общем, это виртуальные базы A
, C
то не виртуальные базы B
, D
, E
а также D
, F
, а потом G
сам.
Вы можете исследовать порядок вызовов конструктора из этой цитаты C ++ Standard и попытаться перехватить его самостоятельно
10 В не делегирующем конструкторе инициализация продолжается в
следующий порядок: — сначала и только для конструктора самого
производный класс (1.8), виртуальные базовые классы инициализируются в порядке
они появляются на глубине первого слева направо обхода направленного
ациклический граф базовых классов, где «слева направо» — это порядок
Появление базовых классов в производном классе
базовый спецификатор-лист. — Затем прямые базовые классы инициализируются в
порядок декларирования в том виде, в котором он указан в списке базовых спецификаторов
(независимо от порядка установки mem-инициализаторов). — Тогда не статично
члены данных инициализируются в том порядке, в котором они были объявлены в
определение класса (опять же, независимо от порядка
MEM-инициализаторы). — Наконец, составное заявление
тело конструктора выполнено. [Примечание: порядок декларации
поручено обеспечить уничтожение базовых и членских подобъектов в
обратный порядок инициализации. —Конечная записка]