C ++ конструктор и порядок деструкторов - PullRequest
10 голосов
/ 27 марта 2012

Я пытаюсь написать код о создании и уничтожении базового класса и члена, и я запутался в каком-то порядке конструктора и деструктора. Вывод этого кода:

Base1 constructor
Member1 constructor
Member2 constructor
Derived1 constructor
Member3 constructor
Member4 constructor
Derived2 constructor
Derived2 destructor
Member4 destructor
Member3 destructor
Derived1 destructor
Member2 destructor
Member1 destructor
Base1 destructor

См. Первые четыре строки,но я упал заказ должен быть

Base1 constructor
Derived1 constructor
Member1 constructor
Member2 constructor

Кто-нибудь может дать мне некоторые объяснения?

#include "stdafx.h"
#include <fstream>
using namespace std;
ofstream out("order.out");

#define CLASS(ID) class ID { \
public: \
  ID(int) { out << #ID " constructor\n"; } \
  ~ID() { out << #ID " destructor\n"; } \
};

CLASS(Base1);
CLASS(Member1);
CLASS(Member2);
CLASS(Member3);
CLASS(Member4);

class Derived1 : public Base1 {
  Member1 m1;
  Member2 m2;
public:
  Derived1(int) : m2(1), m1(2), Base1(3) {
    out << "Derived1 constructor\n";
  }
  ~Derived1() {
    out << "Derived1 destructor\n";
  }
};

class Derived2 : public Derived1 {
  Member3 m3;
  Member4 m4;
public:
  Derived2() : m3(1), Derived1(2), m4(3) {
    out << "Derived2 constructor\n";
  }
  ~Derived2() {
    out << "Derived2 destructor\n";
  }
};

int main() {
  Derived2 d2;
} ///:~

Ответы [ 5 ]

9 голосов
/ 27 марта 2012

Конструкторы в иерархии вызываются вверх:

- base class member objects
- base class constructor body
- derived class member objects
- derived class constructor body

Вывод правильный.

Давайте упростим ваш код:

struct BaseMember
{
   BaseMember() { cout << "base member" <<endl; }
};
struct Base
{
   BaseMember b;
   Base() { cout << "base" << endl; }
};
struct DerivedMember
{
   DerivedMember() { cout << "derived member" << endl; }
};
struct Derived : public Base
{
   DerivedMember d;
   Derived() { cout << "derived" << endl; }
};

Derived d;

Когда создается d, сначала создается деталь Base. Прежде чем он входит в тело конструктора, все объекты-члены инициализируются. Итак, BaseMember - первый инициализированный объект.

Далее вводится конструктор Base.

До того, как входит конструктор Derived, объекты-члены Derived инициализируются, поэтому создается DerivedMember, вызывается следующий конструктор Derived.

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

EDIT Как указал Матье, порядок, в котором объекты-члены инициализируются, определяется порядком их появления в определении класса, а не порядком, в котором они появляются в списке инициализатора.

2 голосов
/ 27 марта 2012

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

1 голос
/ 26 ноября 2012

Рассмотрим следующую программу, которая прояснит вашу идею!

#include<iostream.h>
class A
{
public:
  A()
    {
    cout<<"\nI am the base class constructor!";
    }
  ~A()
    {
    cout<<"\nI am the base class destructor!";
    }
};

class B : public A
{
public:
  B()
    {
    cout<<"\nI am the derived class constructor!";
    }
  ~B()
    {
    cout<<"\nI am the derived class destructor!";
    }
};

int main()
  {
  B obj;
  return 0;
  }

Вывод вышеуказанной программы будет следующим:

Я конструктор базового класса!

Я - конструктор производного класса!

Я деструктор производного класса!

Я деструктор базового класса!

Я думаю, что это объясняет и уточняет ваш запрос о порядке вызова конструкторов и деструкторов.

1 голос
/ 27 марта 2012

Это просто потому, что m1 и m2 инициализируются в списке инициализации конструктора Derived1.Все в списке инициализации создается до ввода тела конструктора.

1 голос
/ 27 марта 2012

Хорошо, инициализация, выполненная в списке инициализации, происходит перед телом конструктора Derived1, поэтому сначала вы увидите выходные данные для m1 и m2.

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

В этом случае, когда вы создаете Derived2, он сначала переходит к созданию подобъекта Derived1. Это, в свою очередь, включает в себя сначала создание подобъекта Base, поэтому он делает это первым. Затем он создает элементы Derived1, выполняет тело конструктора Derived1, создает элементы Derived2 и, наконец, выполняет тело конструктора Derived2. Отсюда наблюдаемый выход.

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