Bezdepbonusu7Программирование: статьи и ответы

Вопрос

C++: гарантии порядка построения и инициализации

Автор вопроса: Giovanni FunchalОтветов: 5

У меня есть некоторые сомнения относительно гарантий порядка построения и инициализации в 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
  • Порядок будет W, Z, Y, X, но я не уверен в конкретных правилах. Charles Beattie 25.03.2010
  • Какая связь между Y и W? curiousguy 26.08.2015

c++constructorinitialization-order

Ответы

Ответ 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

Ответ 3 · рейтинг 2 · jwismar

  1. Объект W будет создан до вызова конструктора X.
  2. Z, как базовый класс X, будет инициализирован перед членами X.
  3. Y будет инициализирован во время инициализации члена
  4. Конструктор X будет запущен.

Ответ 4 · рейтинг 2 · Edward Strange

Чтобы расширить ответ Чарльза Бейли, правила меняются, когда ваши базовые классы наследуются виртуально. Я всегда забываю, каков порядок, на сайте IBM говорится, что сначала инициализируются виртуальные базы, но я просто никогда не сталкивался со случаем, когда на самом деле это больше, чем просто мелочи.

Ответ 5 · рейтинг 2 · Amit Singh

Если обобщить, то это правила:

  1. Аргументы, взятые справа налево
    а. Самый правый
    b. 2-й справа
  2. Базовый класс
  3. Виртуальная база
  4. Базовые классы слева направо
  5. Члены в порядке объявления в классе
  6. Конструктор вызываемого класса

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы