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 говорится, что сначала инициализируются виртуальные базы, но я просто никогда не сталкивался со случаем, когда это на самом деле больше, чем пустяки.

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

Подводя итог, это правила:

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