Подтвердить что ты не робот

Классный порядок инициализации

class D: A
{
    B obj;
    C obj2;
}

Какой порядок строительства здесь гарантирован?

Я знаю, что D будет построено после A, B и C, но то, что я действительно хочу знать, заключается в том, будет ли A гарантированно построено до B или C, или даже если B гарантированно будет построено до C.

Я знаю, что у вас может быть явный список инициализаторов:

D(): A(), B(), C()
{}

но этот список инициализации определяет порядок инициализации?

Кроме того, делает ли какой-либо из компонентов конструктор по умолчанию или нет?

4b9b3361

Ответ 1

Из стандарта С++ 03 ISO/IEC 14882: 2003 (E) §12.6.2/5 [class.base.init]:

Инициализация должна выполняться в следующем порядке:
- Во-первых, и только для конструктора самого производного класса, как описано ниже, виртуальные базовые классы должны быть инициализированы в том порядке, в каком они появляются на первом пересечении слева направо, направленном ациклическим графом базовых классов, где "слева направо" - это порядок появления имен базового класса в базе-спецификаторе производного класса.
- Затем прямые базовые классы должны быть инициализированы в порядке объявления, как они появляются в списке-спецификаторе-базовом (независимо от порядка mem-инициализаторов).
- Затем нестатические члены данных должны быть инициализированы в том порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-инициализаторов).
- Наконец, выполняется тело конструктора.
[Примечание: заказ декларации уполномочен гарантировать, что субобъекты базы и члена будут уничтожены в обратном порядке инициализации. ]

Итак, в этом случае вам гарантируется, что порядок инициализации будет сначала базовым классом A, а затем подобъектом B (поскольку он появляется первым в списке членов класса в определении класса), тогда подобъектом C. Порядок списка инициализаторов не имеет значения, равно как и какой-либо из членов имеет или не имеет конструктора по умолчанию - если член не имеет конструктора по умолчанию и он явно не инициализирован в списке инициализаторов, то он имеет неопределенное значение.

Ответ 2

но этот список инициализации определяет ORDER инициализации?

Нет. Инициализационный список не определяет порядок инициализации данных-членов и базового подобъекта (ов). Члены инициализируются в порядке их объявления, а базовые подобъекты строятся в порядке их упоминания - слева направо:

struct A : B, C {}  //B is constructed before C

Кроме того, базовые подобъекты создаются до инициализации данных элемента.

struct A : B, C 
{
      D d;
      E e;
};

Порядок инициализации в приведенной выше структуре:

    B     =>    C      =>   d    =>   e   
subobject   subobject     member    member

И они уничтожены в обратном порядке.

Ответ 3

Возможно, этот пример разбитого кода поможет проиллюстрировать:

Если я определяю такой класс:

class Connection {

   boost::asio::tcp::ip::socket _socket;
   boost::asio::io_service _io_service;

   Connection() : _io_service(), _socket(_io_service)
   {
   }
};

Это не удастся во всех современных компиляторах. Поскольку _socket определяется сначала как член класса, список инициализации сначала попытается инициализировать его, несмотря на то, что список инициализации просит компилятор сначала инициализировать _io_service. Но поскольку _io_service еще не инициализирован (конструктор сокета зависит от инициализированного _io_service), инициализация _socket приведет к segfault.

Возможно, кто-то может процитировать соответствующий раздел стандарта, который диктует это поведение.

Во второй половине вопроса базовые классы всегда будут инициализированы перед собственными членами классов.