C++: Гарантии порядка построения и инициализации
У меня есть некоторые сомнения в отношении порядка построения и порядка инициализации в 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
5 ответов
Во всех классах гарантирован порядок построения: базовые классы, указанные слева направо, за которыми следуют переменные-члены в порядке, объявленном в определении класса. Тело конструктора класса выполняется после того, как все конструкции его баз и членов завершены.
В вашем примере X
происходит от Z
и содержит Y
Итак Z
сначала строится базовый объект, затем Y
член y
затем строительство X
завершается с исполнением X
конструктор тела.
Временный W
необходимо перейти к конструктору X
таким образом, он построен до строительства x
начинается и будет уничтожен после инициализации x
завершается.
Таким образом, программа должна напечатать:
W
Z
Y
X
1) Прежде всего, необходимо рассчитать аргументы.
2) Затем строятся базовые классы.
3) Затем члены строятся в порядке появления в объявлении класса.
4) Тогда конструктор X называется
Чтобы расширить ответ Чарльза Бейли, правила меняются, когда ваши базовые классы наследуются виртуально. Я всегда забываю, каков порядок, на сайте IBM говорится, что сначала инициализируются виртуальные базы, но я просто никогда не сталкивался со случаем, когда это на самом деле больше, чем пустяки.
- Объект W будет создан до вызова конструктора X.
- Z, как базовый класс X, будет инициализирован перед членами X.
- Y будет инициализирован во время инициализации члена
- Конструктор X будет работать.
Подводя итог, это правила:
- Аргументы взяты справа налево
а. Право Мост
б. 2-й справа - Базовый класс
- Виртуальная база
- Базовые классы слева направо
- Члены в порядке объявления в классе
- Конструктор вызываемого класса