1) Основная причина этого - Derived
класс должен иметь доступ к Base
полям класса.
Позвольте мне объяснить на примере:
class Base {
public:
Base(): m_i(10) {}
protected:
int m_i;
};
class Derived: public Base {
public:
Derived(): m_f(100.0) {
m_i = 1;
}
void print() {
std::cout << "Derived m_f=" << m_f << ", m_i=" << m_i << '\n';
}
private:
float m_f;
};
int main() {
Derived d;
d.print(); // prints: "Derived m_f=100, m_i=1"
}
Если инициализация произошла наоборот: Derived
может получить доступ к неинициализированным данным в Base
, что плохо.
Также конструктор Derived()
не сможет правильно изменить значения поля Base
, и вы будет напечатано «Derived m_f=100, m_i=10
», потому что m_i=1;
в Derived()
будет первым, а m_i{10}
- следующим, и это просто сбивает с толку.
2) Я могу подумать и о другой причине :
Представьте себе следующее - Base()
конструктор генерирует исключение и должен очистить его после себя.
Если мы уже инициализировали Derived
, это означало бы, что теперь нам нужно очистить после Derived
тоже, это накладные расходы.