9
votes

Est-ce que c ++ crée-t-on par défaut "Constructor / Destructor / Copier Copy Coast Operateur d'attribution de copie" pour une classe virtuelle pure?

Les compilateurs de C ++ génèrent les fonctions par défaut telles que Constructor / Destructor / Copy-Constructor ... pour cette "classe"?

class IMyInterface
{
    virtual void MyInterfaceFunction() = 0;
}


2 commentaires

= 0; est uniquement autorisé à suivre la fonction virtuelle.


@BILLZ et Lightness Courses en orbite: corrigé


4 Réponses :


1
votes

En outre, je wannt de savoir s'il est raisonnable de définir un destructeur virtuel pour une interface virtuelle pure, comme celle ci-dessus? (Ainsi, aucun pointeur ni données n'est utilisé ici, rien ne doit être détruit)

Ce n'est pas seulement raisonnable, il est recommandé. En effet, dans le cas des hiérarchies de fonction virtuelles, (automatiquement) appeler un destructeur d'une classe spécialisée appelle également tous les destructeurs de ses classes de base. S'ils ne sont pas définis, vous devez obtenir une erreur de liaison.

Si vous définissez au moins une fonction virtuelle de votre classe, vous devez également définir un destructeur virtuel.

Le destructeur peut être défini avec = par défaut cependant:

Voici un code corrigé (compilable) exemple: xxx


1 commentaires

La définition aurait besoin d'aller dans le fichier .cpp ou, sinon vous devez ajouter le mot-clé inline . De plus, quel est le point dans la définition du destructeur comme pur virtuel quand un autre membre a déjà marqué la classe comme abstrait?



3
votes

oui.

Il n'y a pas de libellé qui oblige la classe à être instanciable pour que ces fonctions membres spéciales soient qualifiées implicitement.

C'est un sens - juste Parce que vous ne pouvez pas instancier la base, cela ne signifie pas qu'une classe dérivée ne veut pas utiliser ces fonctions. xxx

voir:

  • §12.1 / 5 (CTOR)
  • §12.8 / 9 (déplacement)
  • §12.8 / 20 (copie)

2 commentaires

"Ne veut pas utiliser ces fonctions" est bien sûr une façon très douce de la mettre - je ne vois aucune façon que le constructeur et le destructeur puissent même l'éviter. Après tout, le constructeur de classe de base est appelé avant que le corps du constructeur de classe dérivé soit entré, et inversement pour les destructeurs.


@Christophercreutzig: En effet.



1
votes

En outre, je wannt de savoir s'il est raisonnable de définir un destructeur virtuel pour une interface virtuelle pure, comme celle ci-dessus? (Ainsi, aucun pointeur ni données n'est utilisé ici, rien ne doit être détruit)

Les classes dérivées feront-elles jamais quelque chose dans leurs destructeurs? Pouvez-vous être certain qu'ils ne le feront jamais, même lorsque quelqu'un d'autre prend le développement?

Le point d'avoir un destructeur virtuel n'est pas de s'assurer que la classe de base est correctement détruite, cela se produira de toute façon. Le point est que le destructeur de la classe dérivée est appelé lorsque vous utilisez une interface générique: xxx

lorsque A est hors de portée, pourquoi est le < Code> ifstream fermé? Parce que le destructeur supprime l'objet à l'aide du destructeur virtuel.


0 commentaires

0
votes

Ceci aborde la deuxième question concernant la déclaration d'un destructeur virtuel pour une classe de base abstraite (par ex. Au moins une fonction membre est pur virtuel). Voici un exemple de monde réel du compilateur LLVM Clang ++ attrapant un problème potentiel. Ceci s'est produit avec la version d'outils de ligne de commande fournie par Apple Developer pour le système d'exploitation Mac OS X Mavericks.

Supposons que vous disposiez d'une collection de classes dérivées qui ont finalement le parent avec la classe de base abstraite pour définir l'interface commune. Ensuite, il est nécessaire d'avoir un conteneur de stockage comme un vecteur intentionnellement déclaré pour stocker un pointeur sur la classe de base abstraite pour chaque élément. Plus tard, après de bonnes pratiques d'ingénierie, les éléments de conteneur doivent être «supprimés» et la mémoire renvoyée au tas. Le moyen le plus simple de le faire est de traverser l'élément vectoriel par élément et d'appeler l'opération Supprimer sur chacune d'elles.

Eh bien, si la classe de base abstrait ne déclare pas le destructeur en tant que virtuel, le compilateur Clang ++ offre un avertissement amical sur appeler le destructeur non virtuel sur une classe abstraite. N'oubliez pas que, en réalité, seules les classes dérivées sont attribuées du tas avec opérateur neuf. Le type de pointeur de classe dérivé de la relation d'héritage est en effet le type de classe de base abstrait (par exemple, la relation est-une relation).

Si le destructeur de la classe de base abstrait n'est pas virtuel, alors comment le destructeur de classe dérivée correcte sera-t-il invoqué pour libérer la mémoire? Au mieux, le compilateur sait mieux (au moins potentiellement avec C ++ 11) et le rend. Si l'option de compilateur -wall est activée, au moins, l'avertissement de compilation doit apparaître. Cependant, en pire, le destructeur de classe dérivé n'est jamais atteint et la mémoire n'est jamais retournée au tas. Par conséquent, il y a maintenant une fuite de mémoire qui peut être très difficile à suivre et à réparer. Tout ce qu'il faudra est un seul ajout de "virtuel" à la déclaration destructeurs de la classe de base abstraite.

code d'exemple: xxx

pour résoudre cette mémoire potentielle Fuite, la classe de base abstrait doit déclarer son destructeur comme virtuel. Rien d'autre n'est requis. La classe de base abstrait devient maintenant: xxx

Notez que la classe de base abstraite a actuellement des corps de constructeur et de destructeurs vides. Comme la légèreté a répondu ci-dessus, le compilateur crée un constructeur de constructeur, destructeur et de copie par défaut pour une classe de base abstraite (si non définie par l'ingénieur). Il est fortement recommandé de passer en revue l'une des éditions de programmation de programmation C ++ par le Créateur C ++, Bjarne Stroustrup, pour plus de détails sur les classes de base abstraites.


0 commentaires