Являются ли конструкторы родительских классов до инициализации переменных?
Созданы ли конструкторы родительских классов до инициализации переменных, или компилятор сначала инициализирует переменные класса?
Например:
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 будет иметь случайное значение, если нет конструктора по умолчанию, который инициализирует его.