84 votes

Classe dérivée avec destructeur non virtuel

Existe-t-il des circonstances dans lesquelles il est légitime pour une classe dérivée d'avoir une classe non dérivée ? virtual destructeur ? Un non virtual destructeur signifie qu'une classe ne doit pas être utilisée comme classe de base. Le fait d'avoir une classe non virtual d'une classe dérivée agit comme une forme faible de la méthode Java final modificateur ?

Je suis particulièrement intéressé par le cas où la classe de base de la classe dérivée possède une classe de type virtual destructeur.

2voto

Mark Ransom Points 132545

Si votre classe dérivée n'ajoute aucun membre de données à la classe de base, et a un corps de destructeur vide, alors il n'y aura pas d'importance si le destructeur est virtuel ou non - tout ce que le destructeur dérivé fera est d'appeler celui de la base de toute façon. Ce n'est pas recommandé parce qu'il est beaucoup trop facile pour quelqu'un de venir et de modifier la classe sans être conscient de ces restrictions.

Si vous n'essayez jamais de supprimer un objet par le biais d'un pointeur vers la classe de base, vous serez en sécurité. Il s'agit d'une autre règle difficile à appliquer et qui doit être utilisée avec précaution.

Parfois, vous n'avez aucun contrôle sur la classe de base et vous êtes obligé de dériver de celle-ci, même si le destructeur n'est pas virtuel.

Enfin, avoir un destructeur non virtuel dans la classe de base n'impose aucune restriction à la classe dérivée qui sera appliquée par le compilateur, donc je ne pense pas que cela ressemble du tout à la finale de Java.

1voto

Pavel Radzivilovsky Points 11613

Oui, non et non.

Le destructeur virtuel n'a rien à voir avec la capacité de la classe à être une classe de base ou une classe dérivée. Il est légitime d'être les deux.

Cependant, il existe certaines raisons de rendre les destructeurs virtuels. Voir ici : http://en.wikipedia.org/wiki/Virtual_destructor#Virtual_destructors . Cela permet à une classe, entre autres, d'avoir une table virtuelle si elle n'en a pas déjà une. Cependant, les tables virtuelles ne sont pas requises par le C++ pour faire de l'héritage.

1voto

Karoly Horvath Points 45145

Un destructeur non virtuel est parfaitement acceptable tant que vous ne voulez pas l'utiliser comme pointeur de base pour les classes dérivées lors de la suppression de l'objet.

Si vous utilisez ses classes dérivées de manière polymorphe, en les passant et en les stockant avec un pointeur de base puis en les supprimant, la réponse est non, utilisez un destructeur virtuel.

1voto

Matthieu M. Points 101624

Oui, il y en a :

void dothis(Base const&);

void foo() {
  Derived d;
  tothis(d);
}

Ici, la classe est utilisée de manière polymorphe, mais delete n'est pas appelé, donc tout va bien.

Un autre exemple serait :

std::shared_ptr<Base> create() { return std::shared_ptr<Base>(new Derived); }

car un shared_ptr est en mesure d'utiliser une version non polymorphe de delete (par effacement du type).

J'ai implémenté un avertissement dans Clang spécifiquement pour détecter l'appel de delete sur les classes polymorphes non finales avec des destructeurs non virtuels, donc si vous utilisez clang -Wdelete-non-virtual-dtor il émettra un avertissement spécifique pour ce cas.

0voto

SRF Points 384

Le fait d'avoir un destructeur non virtuel d'une classe dérivée agira-t-il comme une forme faible du modificateur final de Java ?

Pas du tout. Voici ma suggestion pour empêcher les sous-classes en C++ (comme le modificateur final en Java) ; rendre le destructeur privé dans une classe. Ensuite, vous pouvez empêcher la création de sous-classes à partir de celui-ci.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X