Почему данные базового класса инициализируются до данных производного класса - PullRequest
1 голос
/ 18 июня 2020

Рассмотрим этот код:

class Base {
public:
  Base(): m_i{10} {}
private:
  int m_i;
};

class Derived: public Base {
public:
  Derived(): m_f{100.0} {}
private:
  float m_f;
};

int main() {
  Derived d;
}

Когда Derived d; создается, C ++ сначала вызывает Base() конструктор и инициализирует данные Base - m_i - и только затем вызывает Derived() конструктор и инициализирует данные Derived - m_f.

Но в чем причина этого?

Почему C ++ не делает этого по-другому?

Потому что, насколько я могу судить, это не быстрее или что-то в этом роде.

1 Ответ

3 голосов
/ 18 июня 2020

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 тоже, это накладные расходы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...