Si j'ai une classe de base avec un destructeur virtuel. A une classe dérivée pour déclarer un destructeur virtuel aussi?
class base {
public:
virtual ~base () {}
};
class derived : base {
public:
virtual ~derived () {} // 1)
~derived () {} // 2)
};
Questions concrètes:
final
pour l'empêcher d'être écrasé dans les classes dérivées, mais cela ne l'empêche pas d'être virtuel.virtual
pour les fonctions virtuelles dans les classes dérivées pour des raisons de clarté. Les gens ne devraient pas avoir à remonter la hiérarchie d'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 tout type (même si vous le définissez comme default
) vous obligera à déclarer les constructeurs de copie et de déplacement et les opérateurs d'affectation si vous les voulez car le compilateur ne les mettra plus pour vous.Comme 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 celle par défaut est une fonction en ligne.
Les fonctions en ligne exposent potentiellement une plus grande partie de votre programme à des modifications 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 beaucoup de recompilation face à certains types de changements. Par exemple, si vous décidez que vous voulez vraiment une implémentation pour votre destructeur virtuel, alors chaque morceau de code qui l'a appelé devra être recompilé. Alors que si vous l'aviez déclaré dans le corps de la classe, puis l'aviez défini vide dans un .cpp
fichier vous seriez bien de le changer 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 par rapport à une implémentation vide. Mais vous pouvez être soumis à des contraintes qui en font un mauvais choix.
Une fonction membre virtuelle rendra implicitement toute surcharge de cette fonction virtuelle.
Ainsi, le virtuel en 1) est "facultatif", le destructeur de classe de base étant virtuel rend également tous les destructeurs enfants virtuels.
1/Oui 2/Oui, il sera généré par le compilateur 3/Le choix entre le déclarer virtuel ou non devrait suivre votre convention pour les membres virtuels remplacés - à mon humble avis, il y a de bons arguments dans les deux sens, choisissez-en un et suivez-le.
Je l'oublierais si possible, mais il y a une chose qui peut vous inciter à le déclarer: si vous utilisez celui généré par le compilateur, il est implicitement en ligne. Il y a du temps où vous voulez éviter les membres en ligne (bibliothèques dynamiques par exemple).