Est-ce que le constructeur et le destructeur d’une classe de base sont appelés avec ceux dérivés?

J’ai une classe appelée MyBase qui a un constructeur et un destructeur:

class MyBase { public: MyBase(void); ~MyBase(void); }; 

et j’ai une classe appelée Banana, qui étend MyBase comme suit:

 class Banana:public MyBase { public: Banana(void); ~Banana(void); }; 

L’implémentation du nouveau constructeur et du nouveau destructeur dans Banana at-elle priorité sur celles de MyBase, ou existe-t-il toujours et est-elle appelée avant ou après l’exécution du constructeur / destructeur de Banana?

Merci, et mes excuses si ma question semble idiote.

Il devrait dire

 class Banana : public MyBase { public: Banana(void); ~Banana(void); }; 

Le constructeur de la classe dérivée est appelé après le constructeur de la classe de base. Les destructeurs sont appelés dans l’ordre inverse.

Un constructeur de base sera toujours appelé avant le constructeur dérivé. Le destructeur de base sera appelé après le destructeur dervidé.

Vous pouvez spécifier sur le constructeur dérivé le constructeur de base que vous souhaitez, sinon le constructeur par défaut sera exécuté.

Si vous définissez d’autres constructeurs mais pas par défaut et ne spécifiez pas sur le constructeur dérivé celui qui sera exécuté, il essaiera les valeurs par défaut qui n’existent pas et entraînera un blocage de la compilation.

Cela se produit car une fois que vous avez déclaré un constructeur, aucun constructeur par défaut n’est généré.

Les constructeurs ne peuvent pas être annulés. Vous ne pouvez pas déclarer un constructeur de classe de base dans une classe dérivée. Un constructeur de classe doit appeler un constructeur dans la classe de base (si aucun n’est spécifié explicitement, le constructeur par défaut est appelé) avant toute autre chose.

Pour pouvoir nettoyer correctement la classe dérivée, vous devez déclarer le destructeur de la classe de base en tant que virtual :

 virtual ~MyBase() { ... } 

Les constructeurs sont appelés top down dans l’arborescence d’inheritance. Cela permet au constructeur dérivé de compter sur l’initialisation complète de l’object de base avant d’essayer d’utiliser les propriétés de la base.

Les destructeurs sont appelés dans l’ordre inverse des constructeurs, pour la même raison: les classes dérivées dépendent de la base, mais la base ne dépend pas des dérivées.

S’il existe une possibilité de détruire l’object via un pointeur sur une classe de base, vous devez déclarer tous les destructeurs virtual .

Les constructeurs et les destructeurs sont des fonctions membres spéciales. En général, vous constaterez partout que la construction commence du type le moins dérivé dans la hiérarchie jusqu’au type le plus dérivé. Il s’agit en réalité de l’ordre dans lequel l’exécution du constructeur s’achève, mais pas du début de la construction.

L’ordre d’exécution de la liste d’initialisation des constructeurs garantit que, même si le constructeur de l’object le plus dérivé sera le premier constructeur à commencer à l’exécuter, ce sera le dernier constructeur à terminer.

Lorsque vous instanciez un object, le constructeur le plus dérivé qui correspond à l’appel de construction est appelé en premier. La liste d’initialisation du constructeur dérivé le plus dérivé correspondant commence et les listes d’initialisation ont un ordre fixe: d’abord, les constructeurs des classes de base dans l’ordre ou l’apparence dans la liste d’inheritance sont appelés. Ensuite, les constructeurs d’atsortingbuts membres sont appelés dans l’ordre dans lequel ils apparaissent dans la déclaration de classe (et non dans l’ordre dans lequel ils apparaissent dans la liste d’initialisation). Une fois que toute la liste d’initialisation (à chaque niveau) est terminée, le bloc du corps du constructeur est exécuté, puis l’appel du constructeur est terminé.

Tous les destructeurs de base seront appelés dans l’ordre inverse de la construction après l’exécution du destructeur le plus dérivé. La destruction se produit dans l’ordre inverse exact de la construction.

Les destructeurs sont spéciaux d’une manière différente: ils ne peuvent pas être annulés. Lorsque vous appelez le destructeur le plus dérivé d’une classe, l’exécution du corps du destructeur est terminée, après quoi tous les destructeurs d’atsortingbuts membres sont appelés dans l’ordre inverse de la création. Une fois que le destructeur le plus dérivé est terminé et que les destructeurs membres de l’object le plus dérivé sont terminés, le destructeur de ses bases les plus directes démarre dans l’ordre de construction inverse, les corps du destructeur s’exécutent, puis les atsortingbuts de membre destructeurs, etc. À la fin, tous les éléments construits seront détruits.

Les destructeurs des classes polymorphes doivent être virtuels

La description de la destruction ci-dessus commence par l’appel du destructeur le plus dérivé. Cela peut être réalisé en appelant delete sur un pointeur vers le type le plus dérivé, lorsqu’un object automatique sort de son champ d’application ou lorsque l’object est delete d via une classe de base dont le destructeur est virtuel.

Si vous oubliez d’append le mot clé destructor dans la classe de base et que vous essayez de supprimer un object dérivé via un pointeur sur la base, vous appellerez directement le destructeur de base, ce qui implique que tous les sous-objects situés sous le type de pointeur dans la hiérarchie ne le seront pas. être correctement détruit. Toutes les hiérarchies d’inheritance dans lesquelles vous allez supprimer des objects via des pointeurs sur un type de base doivent avoir des destructeurs virtuels. En règle générale, si vous avez déjà une méthode virtuelle, le coût de la virtualisation du destructeur est négligeable et constitue un filet sécurisé. De nombreux guides de codage indiquent que les destructeurs dans les hiérarchies d’inheritance doivent être virtuels. Certains vont même jusqu’à demander à tous les destructeurs d’être virtuels. Cela a pour but d’éviter toute fuite de ressource au prix de l’ajout d’une vtable pour tous les types et d’un pointeur vtable pour tous les objects.

Il vous manque le type d’inheritance:

Changement

 class Banana:MyBase 

À:

 class Banana: public MyBase 

Pour ce qui est de

L’implémentation du nouveau constructeur et du nouveau destructeur dans Banana annule-t-elle celles de MyBase ou existe-t-il toujours, et est-elle appelée avant ou après l’exécution du constructeur / destructeur de Banana?

L’ordre des hérités s’exécute de bas en haut, cela signifie que MyBase sera appelé en premier, puis Banana. Si vous aviez une autre sous-classe, elle serait appelée en dernier.

Prenons cet exemple:

 class RottenBanana : public Banana 

La chaîne d’inheritance est maintenant RottenBanana -> Banana -> MyBase

Les constructeurs de cette classe seront appelés à partir de MyBase, puis de Banana, puis de RottenBanana.

Si vous instanciez un object EEGModeRGB (auquel est associée une led sortingcolore) – puis supprimez-le immédiatement, vous verrez les couleurs bleu, vert, jaune et rouge pendant une seconde chacune – dans cet ordre.

 class EEGMode { public: EEGMode() { setAllPixelsToColor(BLUE); delay(1000); } virtual ~EEGMode() { setAllPixelsToColor(RED); delay(1000); } }; class EEGModeRGB : public EEGMode { public: EEGModeRGB() { setAllPixelsToColor(GREEN); delay(1000); } virtual ~EEGModeRGB() { setAllPixelsToColor(YELLOW); delay(1000); } };