Вопрос

У меня есть некоторые сомнения относительно гарантий порядка построения и инициализации в 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
Это было полезно?

Решение

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

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

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

Итак, программа должна напечатать:

W
Z
Y
X

Другие советы

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

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

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

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

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

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

Подводя итог, следующие правила:

  1. Аргументы, взятые справа налево
    а.Самый правый
    б.2-й справа
  2. Базовый класс
  3. Виртуальная база
  4. Базовые классы слева направо
  5. Участники в порядке объявления в классе
  6. Конструктор вызываемого класса
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top