С++:Гарантии порядка построения и инициализации
-
22-09-2019 - |
Вопрос
У меня есть некоторые сомнения относительно гарантий порядка построения и инициализации в C++.Например, следующий код имеет четыре класса X
, Y
, Z
и W
.Основная функция создает экземпляр объекта class X
, который содержит объект class Y
, и происходит от class Z
, поэтому будут вызваны оба конструктора.Кроме того, const char*
параметр, переданный в X
конструктор будет неявно преобразован в объект class W
, так W
Также необходимо вызвать конструктор.
Какие гарантии дает стандарт C++ относительно порядка вызовов конструкторов копирования?Или, что эквивалентно, что этой программе разрешено печатать?
#include <iostream>
class Z {
public:
Z() { std::cout << "Z" << std::endl; }
};
class Y {
public:
Y() { std::cout << "Y" << std::endl; }
};
class W {
public:
W(const char*) { std::cout << "W" << std::endl; }
};
class X : public Z {
public:
X(const W&) { std::cout << "X" << std::endl; }
private:
Y y;
};
int main(int, char*[]) {
X x("x");
return 0;
}
редактировать:Это верно?
W |
/ \ |
Z Y |
\ / |
X V
Решение
Во всех классах порядок строительства гарантирован:базовые классы, как указано слева направо, за которыми следуют переменные-члены в порядке, указанном в определении класса.Тело конструктора класса выполняется после завершения всех конструкций его баз и членов.
В вашем примере X
получено из Z
и содержит Y
Итак Z
сначала создается базовый объект, затем Y
член y
, то строительство X
завершается выполнением X
тело конструктора.
Временный W
необходимо передать конструктору X
, поэтому он строится до построения x
начинается и будет уничтожен после инициализации x
завершает.
Итак, программа должна напечатать:
W
Z
Y
X
Другие советы
1) Прежде всего необходимо посчитать аргументы.
2) Затем строятся базовые классы.
3) Затем члены конструируются в порядке появления в объявлении класса.
4) Тогда конструктор X называется
- Объект W будет создан до вызова конструктора X.
- Z, как базовый класс X, будет инициализирован перед членами X.
- Y будет инициализирован во время инициализации члена
- Конструктор X будет запущен.
Если расширить ответ Чарльза Бейли, правила меняются, когда ваши базовые классы наследуются виртуально.Я всегда забываю, в каком порядке, на сайте IBM написано, что сначала инициализируются виртуальные базы, но я никогда не сталкивался со случаем, когда это на самом деле было чем-то большим, чем пустяки.
Подводя итог, следующие правила:
- Аргументы, взятые справа налево
а.Самый правый
б.2-й справа - Базовый класс
- Виртуальная база
- Базовые классы слева направо
- Участники в порядке объявления в классе
- Конструктор вызываемого класса