Existe-t-il une bonne raison de ne pas déclarer un destructeur virtuel pour une classe? Quand faut-il éviter spécifiquement d'en écrire un?
Réponses
Trop de publicités?Il n'est pas nécessaire d'utiliser un destructeur virtuel lorsque l'une des conditions ci-dessous est vraie:
- Aucune intention d'en tirer des cours
- Pas d'instanciation sur le tas
- Aucune intention de stocker dans un pointeur d'une super-classe
Aucune raison spécifique pour l'éviter à moins d'être vraiment pressé par la mémoire.
Pour répondre à la question explicitement, c'est à dire. quand devriez-vous pas déclarer un destructeur virtuel.
L'ajout d'un destructeur virtuel peut changer votre classe de POD (Plain Old Données)*
ou Agrégées Non-POD. Cela peut empêcher votre projet à partir de la compilation si votre classe est de type agrégat initialisé quelque part.
Dans un cas extrême, une telle modification peut également provoquer un comportement indéterminé où la classe est utilisé n une manière qui nécessite un module, par exemple. en passant par des points de suspension paramètre, ou de l'utiliser avec memcpy.
*
D'un type POD est un type qui a des garanties spécifiques au sujet de sa disposition de la mémoire. La norme vraiment indique seulement que si vous copiez à partir d'un objet avec un type POD dans un tableau de caractères (ou non signé caractères) et de retour à nouveau, alors le résultat sera le même que l'objet d'origine.]
Je déclare un destructeur virtuel si et seulement si j'ai des méthodes virtuelles. Une fois que j'ai des méthodes virtuelles, je ne me fais pas confiance pour éviter de l'instancier sur le tas ou de stocker un pointeur sur la classe de base. Ces deux opérations sont extrêmement courantes et entraînent souvent des fuites silencieuses de ressources si le destructeur n’est pas déclaré virtuel.
Un destructeur virtuel est nécessaire à chaque fois que il y a toute chance qu' delete
pourrait être appelé un pointeur vers un objet d'une sous-classe du type de votre classe. Cela vous permet de vérifier le bon destructeur est appelé au moment de l'exécution, sans que le compilateur avoir à connaître la classe d'un objet sur le tas au moment de la compilation. Par exemple, supposons B
est une sous-classe de A
:
A *x = new B;
delete x; // ~B() called, even though x has type A*
Si votre code n'est pas critique pour les performances, il serait raisonnable d'ajouter un destructeur virtuel pour chaque classe de base, vous écrire, juste pour la sécurité.
Toutefois, si vous avez trouvé vous-même delete
ing beaucoup d'objets dans une boucle serrée, la charge de l'appel d'une fonction virtuelle (même vide) peut être sensiblement. Le compilateur ne peut pas habituellement inline ces appels, et le processeur peut avoir un moment difficile de prédire où aller. Il est peu probable que cela aurait un impact significatif sur les performances, mais il vaut la peine de mentionner.
Les fonctions virtuelles signifient que chaque objet alloué augmente les coûts de la mémoire grâce à un pointeur de table de fonctions virtuelles.
Donc, si votre programme implique l’allocation d’un très grand nombre d’objets, il serait utile d’éviter toutes les fonctions virtuelles afin d’économiser les 32 bits supplémentaires par objet.
Dans tous les autres cas, vous éviterez les problèmes de débogage pour rendre le serveur virtuel.