Являются ли конструкторы родительских классов до инициализации переменных?

Созданы ли конструкторы родительских классов до инициализации переменных, или компилятор сначала инициализирует переменные класса?

Например:

class parent {
protected:
  int a;
public:
  parent() : a(123) {};
};

class child : public parent {
  int b;
public:
            // question: is parent constructor done before init b?
  child() : b(456), parent() {};
}

Ответ 1

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

12.6.2 Инициализация баз и членов [class.base.init]

В конструкторе без делегирования инициализация продолжается в в следующем порядке:

- Во-первых, и только для конструктора самого производный класс (1.8), виртуальные базовые классы инициализируются в порядке они появляются на первом переходе слева направо направо ациклический граф базовых классов, где "слева направо" - это порядок появление базовых классов в производном классе базовый спецификатор-лист.

- Затем прямые базовые классы инициализируются в порядок декларации, поскольку они отображаются в списке-спецификаторе базы (независимо от порядка mem-инициализаторов).

- Тогда нестатические элементы данных инициализируются в том порядке, в котором они были объявлены в класса (опять же, независимо от порядка MEM-инициализаторы).

- Наконец, составная формулировка тело конструктора выполнено.

Ответ 2

Да, родительский конструктор всегда вызывается перед производным классом. В противном случае производный класс не мог бы "изменить" что-либо, установленное родительским классом.

Ответ 3

Как и некоторые советы, вы можете просто просто проверить такие вещи, если вы не уверены:

#include <iostream>
using namespace std;

class parent {
protected:
  int a;
public:
  parent() : a(123) { cout << "in parent(): a == " << a << endl; };
};

class child : public parent {
  int b;
public:
            // question: is parent constructor done before init b?
  child() : b(456), parent() { cout << "in child(): a == " << a << ", b == " << b << endl; };
};

int main() {
  child c;
  return 0;
}

печатает

in parent(): a == 123
in child(): a == 123, b == 456

Ответ 4

Да, построение объектов начинается с родительского класса и приходит к дочерним классам, поэтому вызовы конструктора находятся в этом порядке. В случае разрушения это совершенно противоположно.

Ответ 5

думать о производном классе как дополнительном добавлении или расширении своего базового класса, добавляя его к чему-то (это уже должно существовать). то другой проблемой является инициализация членов. здесь вы указали конструктор по умолчанию

public:
  parent() : a(123) {};

поэтому элемент будет по умолчанию инициализирован 123, даже если вы создадите родителя следующим образом:

parent p;

если не было конструктора по умолчанию, который инициализирует объект со значением

class parent {
public:
  int a;
};

чем то, что будет по умолчанию в члене, зависит, если класс равен P.O.D, тогда int будет инициализироваться по умолчанию на 0, но если это не так, то есть вы предоставляете больше членов, таких как строка или вектор

class parent {
public:
  int a;
  std::string s;
  std::vector<int> v;
};

int будет иметь случайное значение, если нет конструктора по умолчанию, который инициализирует его.