У меня есть некоторые сомнения относительно гарантий порядка построения и инициализации в C++. Например, следующий код имеет четыре класса X, Y, Z и W. Основная функция создает экземпляр объекта class X, который содержит объект class Y и является производным от class Z, поэтому будут вызваны оба конструктора. Кроме того, параметр const char*, переданный конструктору X, будет неявно преобразован в объект class W, поэтому также должен быть вызван конструктор W.
Какие гарантии дает стандарт С++ в отношении порядка вызовов конструкторов копирования? Или, что то же самое, что этой программе разрешено печатать?
#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
Ответ 1 · рейтинг 23 · CB Bailey
Во всех классах гарантируется порядок построения: базовые классы, указанные слева направо, за которыми следуют переменные-члены в порядке, объявленном в определении класса. Тело конструктора класса выполняется после того, как все его базовые элементы и конструкции членов завершены.
В вашем примере X является производным от Z и содержит Y, поэтому сначала создается базовый объект Z, затем член Y y, затем построение X завершается выполнением тела конструктора X.
Временный W необходим для передачи конструктору X, поэтому он создается до начала построения x и будет уничтожен после завершения инициализации x.
Итак, программа должна вывести:
W
Z
Y
X
Ответ 2 · рейтинг 8 · Alexey Malistov
1) В первую очередь нужно вычислить аргументы.
2) Затем строятся базовые классы.
3) Затем члены строятся в порядке появления в объявлении класса.
4) Затем вызывается конструктор X
Ответ 4 · рейтинг 2 · Edward Strange
Чтобы расширить ответ Чарльза Бейли, правила меняются, когда ваши базовые классы наследуются виртуально. Я всегда забываю, каков порядок, на сайте IBM говорится, что сначала инициализируются виртуальные базы, но я просто никогда не сталкивался со случаем, когда на самом деле это больше, чем просто мелочи.