- Oui, c'est la même chose. Le fait que la classe dérivée ne déclare pas quelque chose de virtuel ne l'empêche pas de l'être. En fait, il n'y a aucun moyen d'empêcher une méthode (y compris le destructeur) d'être virtuelle dans une classe dérivée si elle l'était dans une classe de base. En >=C++11, vous pouvez utiliser
final
pour l'empêcher d'être surchargée dans les classes dérivées, mais cela ne l'empêche pas d'être virtuelle.
- Oui, un destructeur dans une classe dérivée peut être omis s'il n'a rien à faire. Et le fait qu'il soit virtuel ou non n'a pas d'importance.
- Je l'omettrais si possible. Et j'utilise toujours soit le
virtual
mot-clé ou override
pour les fonctions virtuelles dans les classes dérivées pour des raisons de clarté. Les gens ne devraient pas avoir à remonter toute la hiérarchie de l'héritage pour comprendre qu'une fonction est virtuelle. De plus, si votre classe est copiable ou déplaçable sans avoir à déclarer vos propres constructeurs de copie ou de déplacement, déclarer un destructeur de n'importe quelle sorte (même si vous le définissez comme default
) vous obligera à déclarer les constructeurs et opérateurs d'affectation copy et move si vous le souhaitez, car le compilateur ne les mettra plus à votre place.
Un petit point pour le point 3. Il a été souligné dans les commentaires que si un destructeur n'est pas déclaré, le compilateur en génère un par défaut (qui est toujours virtuel). Et ce destructeur par défaut est une fonction inline.
Les fonctions en ligne exposent potentiellement une plus grande partie de votre programme à des changements dans d'autres parties de votre programme et rendent la compatibilité binaire pour les bibliothèques partagées délicate. De plus, le couplage accru peut entraîner un grand nombre de recompilations face à certains types de changements. Par exemple, si vous décidez que vous voulez vraiment une implémentation pour votre destructeur virtuel, chaque morceau de code qui l'appelle devra être recompilé. Alors que si vous l'aviez déclaré dans le corps de la classe et que vous l'aviez ensuite défini vide dans une balise .cpp
vous pouvez le modifier sans recompiler.
Mon choix personnel serait toujours de l'omettre lorsque cela est possible. À mon avis, cela encombre le code, et le compilateur peut parfois faire des choses légèrement plus efficaces avec une implémentation par défaut qu'avec une implémentation vide. Mais il y a des contraintes auxquelles vous pouvez être soumis qui font que c'est un mauvais choix.