C ++: Гарантии порядка построения и инициализации - PullRequest
12 голосов
/ 25 марта 2010

У меня есть некоторые сомнения относительно гарантий порядка построения и инициализации в C ++. Например, следующий код имеет четыре класса X, Y, Z и W. Функция main создает экземпляр объекта 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 ]

18 голосов
/ 25 марта 2010

Во всех классах гарантирован порядок построения: базовые классы, указанные слева направо, за которыми следуют переменные-члены в порядке, объявленном в определении класса. Тело конструктора класса выполняется после завершения всех конструкций его баз и членов.

В вашем примере X является производным от Z и содержит Y, поэтому сначала создается базовый объект Z, затем Y member y, затем завершается построение X с выполнением тела конструктора X.

Временный W необходим для передачи конструктору X, поэтому он создается до начала построения x и будет уничтожен после завершения инициализации x.

Итак, программа должна вывести:

W
Z
Y
X
7 голосов
/ 25 марта 2010

1) Прежде всего, необходимо вычислить аргументы.

2) Затем создаются базовые классы.

3) Затем элементы создаются в порядке появления в объявлении класса.

4) Тогда конструктор X называется

2 голосов
/ 26 августа 2015

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

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

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

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