Quel est l’ordre dans lequel les destructeurs et les constructeurs sont appelés en C ++

Quel est l’ordre dans lequel les destructeurs et les constructeurs sont appelés en C ++? Utilisation des exemples de certaines classes de base et classes dérivées

La commande est:

  1. Constructeur de base
  2. Constructeur dérivé
  3. Destructeur dérivé
  4. Destructeur de base

Exemple:

class B { public: B() { cout<<"Construct B"< 

Sortie de l'exemple:

Construire B

Construire D

Destruct D

Détruire B

Plusieurs niveaux d'inheritance fonctionnent comme une stack:

Si vous envisagez de pousser un object sur la stack en tant que construction et de le supprimer en tant que destruction, vous pouvez alors considérer plusieurs niveaux d'inheritance comme une stack.

Cela fonctionne pour n'importe quel nombre de niveaux.

L'exemple D2 dérive de D dérivant de B.

Poussez B sur la stack, appuyez sur D sur la stack, poussez D2 sur la stack. L'ordre de construction est donc B, D, D2. Ensuite, pour trouver l'ordre de destruction, commencez par sauter. D2, D, B

Des exemples plus compliqués:

Pour des exemples plus compliqués, veuillez consulter le lien fourni par @JaredPar

Une description détaillée de ces événements, y compris l’inheritance virtuel et multiple, est disponible sur la FAQ C ++ Lite. Articles 25.14 et 25.15

https://isocpp.org/wiki/faq/multiple-inheritance#mi-vi-ctor-order

De plus, gardez à l’esprit que lorsque les éléments du tableau sont construits en premier -> dernier, ils sont détruits dans l’ordre inverse: last -> first.

Je dois append aux réponses précédentes parce que tout le monde semble l’ignorer

Quand une instance de classe dérivée est créée , il est vrai que le code à l’ intérieur du constructeur de la base sera appelé avant le code à l’ intérieur du constructeur du dérivé , mais gardez à l’esprit que le dérivé est toujours “créé” techniquement avant le base .

Et lorsque le destructeur de classe dérivé est appelé, il est vrai que le code à l’ intérieur du destructeur dérivé est appelé avant le code à l’ intérieur du destructeur de base, mais gardez également à l’esprit que la base est détruite avant le dérivé .

Quand je dis créé / détruit, je me réfère en fait à alloué / désalloué .

Si vous examinez la disposition de mémoire de ces instances, vous verrez que l’instance dérivée compose l’instance de base. Par exemple:

Mémoire de dérivée: 0x00001110 à 0x00001120

Mémoire de base: 0x00001114 à 0x00001118

Par conséquent, la classe dérivée doit être allouée AVANT la base dans la construction. Et la classe dérivée doit être désallouée APRÈS la base dans la destruction.

Si vous avez le code suivant:

 class Base { public: Base() { std::cout << "\n Base created"; } virtual ~Base() { std::cout << "\n Base destroyed"; } } class Derived : public Base { public: Derived() // Derived is allocated here // then Base constructor is called to allocate base and prepare it { std::cout << "\n Derived created"; } ~Derived() { std::cout << "\n Derived destroyed"; } // Base destructor is called here // then Derived is deallocated } 

Donc, si vous avez créé Derived d; et si elle était hors de scope, vous obtiendrez la sortie dans la réponse de @ Brian. Mais le comportement de l'object en mémoire n'est pas vraiment dans le même ordre, il ressemble plus à ceci:

Construction:

  1. Dérivé atsortingbué

  2. Base allouée

  3. Constructeur de base appelé

  4. Constructeur dérivé appelé

Destruction:

  1. Destructeur dérivé appelé

  2. Destructeur de base appelé

  3. Base désallouée

  4. Dérivé désalloué