Ответ
Порядок вызова конструкторов в C++ жёстко фиксирован и происходит снизу вверх — от базовых частей к производным:
- Конструкторы базовых классов. Вызываются в порядке их перечисления в списке наследования (слева направо).
- Конструкторы членов класса (полей). Вызываются в порядке их объявления в определении класса, независимо от порядка в списке инициализации конструктора.
- Тело конструктора самого класса.
Деструкторы вызываются в строго обратном порядке.
Пример с множественным наследованием и полями:
#include <iostream>
#include <string>
class BaseA {
public:
BaseA() { std::cout << "BaseA constructor.n"; }
};
class BaseB {
public:
BaseB() { std::cout << "BaseB constructor.n"; }
};
class MemberX {
public:
MemberX() { std::cout << "MemberX constructor.n"; }
};
class MemberY {
public:
MemberY() { std::cout << "MemberY constructor.n"; }
};
// Наследование: BaseA, затем BaseB
// Объявление полей: MemberX mX, затем MemberY mY
class Derived : public BaseA, public BaseB {
MemberX mX;
MemberY mY;
public:
// Список инициализации не влияет на порядок вызова конструкторов
Derived() : mY(), mX() { // Порядок здесь роли не играет
std::cout << "Derived constructor body.n";
}
};
int main() {
Derived d;
return 0;
}
Вывод программы (порядок вызова):
BaseA constructor. // 1. Базовый класс (первый в списке наследования)
BaseB constructor. // 2. Базовый класс (второй в списке наследования)
MemberX constructor. // 3. Поле (первое в объявлении класса)
MemberY constructor. // 4. Поле (второе в объявлении класса)
Derived constructor body. // 5. Тело конструктора Derived Ответ 18+ 🔞
Э, бля, слушай сюда, про конструкторы в плюсах. Тут, понимаешь, порядок вызова — это не просто так, наобум. Он жёстко зафиксирован, как будто тебе в армии распорядок дня выдали, и никаких отступлений. Идёт он, ёпта, снизу вверх — то есть от самых базовых штук к тем, что на них надстроены. Представь, что ты дом строишь: сначала фундамент, потом стены, потом крышу. Так и тут.
Вот смотри, как это работает, по шагам:
- Конструкторы базовых классов. Берутся по очереди, как они в списке наследования записаны. Слева направо, без вариантов.
- Конструкторы членов класса (полей). А вот это, бля, хитрая жопа! Вызываются они строго в том порядке, в каком ты их в классе объявил. И похуй, в каком порядке ты их в списке инициализации конструктора написал! Ты хоть задом наперёд их там перечисли — порядок вызова не изменится. Вот такая мудя.
- Тело конструктора самого класса. И только в самом конце, когда всё уже собрано и готово, выполняется код внутри фигурных скобок твоего конструктора.
А деструкторы, ясное дело, работают ровно наоборот — вызываются в строго обратном порядке. Разобрали крышу, потом стены, потом фундамент. Логично же.
Вот тебе пример, чтобы вообще всё стало понятно, как будто в рот мне чих-пых:
#include <iostream>
#include <string>
class BaseA {
public:
BaseA() { std::cout << "BaseA constructor.n"; }
};
class BaseB {
public:
BaseB() { std::cout << "BaseB constructor.n"; }
};
class MemberX {
public:
MemberX() { std::cout << "MemberX constructor.n"; }
};
class MemberY {
public:
MemberY() { std::cout << "MemberY constructor.n"; }
};
// Наследование: BaseA, затем BaseB
// Объявление полей: MemberX mX, затем MemberY mY
class Derived : public BaseA, public BaseB {
MemberX mX;
MemberY mY;
public:
// Список инициализации не влияет на порядок вызова конструкторов
Derived() : mY(), mX() { // Порядок здесь роли не играет
std::cout << "Derived constructor body.n";
}
};
int main() {
Derived d;
return 0;
}
И что же эта программа наваяет? Вот вывод, смотри:
BaseA constructor. // 1. Базовый класс (первый в списке наследования)
BaseB constructor. // 2. Базовый класс (второй в списке наследования)
MemberX constructor. // 3. Поле (первое в объявлении класса, хоть в списке инициализации оно второе!)
MemberY constructor. // 4. Поле (второе в объявлении класса, хоть в списке инициализации оно первое!)
Derived constructor body. // 5. И только теперь — тело конструктора Derived
Вот, понимаешь? Компилятору доверия ебать ноль в этом плане — он делает всё по своим правилам, а не так, как тебе в голову взбредёт. Запомни этот порядок, а то потом будешь охуевать, откуда ноги у багов растут.