web-dev-qa-db-fra.com

Le destructeur par défaut peut-il être généré automatiquement en tant que destructeur virtuel?

Le destructeur par défaut peut-il être généré automatiquement en tant que destructeur virtuel?

Si je définis une classe de base mais pas de destructeur par défaut, y a-t-il un destructeur virtuel par défaut généré automatiquement?

52
user53670

Non. La virtualisation d'une méthode a un coût et C++ a pour philosophie de ne pas vous faire payer pour des choses que vous ne déclarez pas explicitement que vous souhaitez utiliser. Si un destructeur virtuel avait été généré automatiquement, vous en auriez payé le prix automatiquement.

Pourquoi ne pas simplement définir un destructeur virtuel vide?

45
Uri

En C++ 11, vous pouvez utiliser:

class MyClass
{
  // create a virtual, default destructor
  virtual ~MyClass() = default;
};
49
Drew Noakes

Non, tous les destructeurs ne sont PAS par défaut virtuels.

Vous devrez définir un destructeur virtuel sur toutes les classes de base

En plus de ça.

Pour citer Scott Meyers dans son livre "Effective C++":

Le standard du langage C++ est exceptionnellement clair sur ce sujet. Lorsque vous essayez de supprimer un objet de classe dérivée via un pointeur de classe de base et que la classe de base a un destructeur non virtuel (comme le fait EnemyTarget), les résultats ne sont pas définis

Dans la pratique, c'est généralement une bonne idée de définir une classe avec un destructeur virtuel si vous pensez que quelqu'un pourrait éventuellement en créer une classe dérivée. J'ai tendance à faire en sorte que toutes les classes aient un destructeur virtuel de toute façon. Oui, il y a un coût associé à cela, mais le coût de ne pas le rendre virtuel plus souvent qui ne pèse pas un lourd fardeau de temps d'exécution.

Je suggère de le rendre non virtuel uniquement lorsque vous êtes absolument certain de le vouloir de cette façon plutôt que de vous fier au non virtuel par défaut que les compilateurs appliquent. Vous pouvez être en désaccord, cependant (en résumé) J'ai récemment eu une fuite de mémoire horrible sur un code hérité où tout ce que j'ai fait a été d'ajouter un std :: vector dans l'une des classes qui existaient depuis plusieurs années. Il s'avère que l'une de ses classes de base n'avait pas de destructeur défini (le destructeur par défaut est vide, non virtuel!) Et comme aucune mémoire n'était allouée comme ça avant qu'aucune mémoire ne fuit jusqu'à ce point. De nombreux jours d'enquête et du temps perdu plus tard ...

9
Matt

Oui, en héritant d'une classe de base avec un destructeur virtuel. Dans ce cas, vous payez déjà le prix d'une classe polymorphe (par exemple vtable).

9
MSalters

Uri et Michael ont raison - j'ajouterai simplement que si ce qui vous dérange est de toucher deux fichiers pour déclarer et définir le destructeur, il est parfaitement normal d'en définir un minimum en ligne dans l'en-tête:

class MyClass
{
   // define basic destructor right here
   virtual ~MyClass(){}

   // but these functions can be defined in a different file
   void FuncA();
   int FuncB(int etc);
}
8
Crashworks

Actuellement, ri a raison. D'un autre côté, après avoir déclaré une méthode virtuelle dans votre classe, vous payez quand même le prix de l'existence de la table virtuelle. En fait, le compilateur vous avertira si votre classe a une méthode virtuelle, mais pas de destructeur virtuel. Cela pourrait devenir un candidat pour la génération automatique du destructeur virtuel par défaut au lieu de l'avertissement embêtant.

2
Thinkeye

Non. Vous devez le déclarer virtuel.

1