class A {
public:
A() { }
~A() { cout << "A Destructor \n" ; }
};
class B :public A{
public:
B() { }
virtual ~B() { cout << "B Destructor \n" ; }
};
class C : public B {
public:
C() { }
~C() { cout << "C Destructor \n"; }
};
int main()
{
A *pointA = new A;
A *pointB = new B;
A *pointC = new C;
delete pointA;
delete pointB;
delete pointC;
}
Répondre
Il invoquera un comportement non défini lors de la deuxième (et troisième) suppression, car le destructeur de A n'est pas virtuel.
§5.3.5/3:
si le type statique de l'opérande est différent de son type dynamique, le type statique est une classe de base de type dynamique de l'opérande et le type statique doit avoir un destructeur virtuel ou le comportement est indéfini.
Si vous faites le destructor d'un comportement virtuel, vous obtenez bien défini, et la destructor du type dynamique est appelée. (Et chacun de ceux appelle à son tour la destructor de base.) Votre sortie serait:
A destructor
B destructor
A destructor
C destructor
B destructor
A destructor
Pour ce que ça vaut, quand vous êtes si près d'un extrait compilable, vous devriez laisser t il inclut. En outre, il suffit d'utiliser struct
au lieu de class
pour être concis sur les choses public
, et laisser de côté les constructeurs vides.
Merci beaucoup Gman. – user373215
Comme GMan l'a souligné, tenter d'appeler l'opérateur delete sur un pointeur de base nécessite un destructeur virtuel pour que le compilateur puisse détruire correctement les objets de la sous-classe. Beaucoup de gens simplifient cela à une règle comme, "Si une classe a des fonctions virtuelles, elle a besoin d'un destructeur virtuel." Ce n'est pas nécessairement le cas; Même une classe de base qui n'a pas de fonctions virtuelles a toujours besoin d'un destructeur virtuel si vous voulez permettre aux clients de supprimer la classe via un pointeur de base. Si vous ne le faites pas, le destructeur devrait être protégé et non public.
Il y a un excellent livre qui décrit ceci en détail et plus appelé C++ Coding Standards par Herb Sutter. Je le recommande comme point de départ dans vos aventures en C++. :-)
- 1. Que fait le code C# suivant?
- 2. Comment faire le code Linq/Lambda suivant?
- 3. Que doit faire un caractère d'échappement si le caractère suivant n'a pas besoin d'être échappé?
- 4. Est-ce que le code C++ valide est le suivant?
- 5. Aide dans le code suivant
- 6. Le code C suivant est-il sécurisé?
- 7. Est-ce que le code suivant appelle un comportement indéterminé?
- 8. Pourquoi est-ce que j'obtiens NPE dans le code suivant?
- 9. erreur dans le code suivant
- 10. Que doit faire un contrôleur d'application?
- 11. Est-ce que le code javascript doit commencer par "<! -"?
- 12. Quel est le problème avec le code suivant?
- 13. explications dictionnaire AppleScript iTunes
- 14. Comment faire pour que mon code mémorise la position actuelle et que la prochaine fois affiche l'élément suivant?
- 15. Comment faire fonctionner l'extrait de code suivant et Comment passer le paramètre à invoquer?
- 16. Comment résoudre les fuites dans le code suivant? ObjectiveC
- 17. Comment améliorer le code suivant dans PHP
- 18. Comment éviter les blocages dans le code C# suivant?
- 19. Boo: est le code suivant possible
- 20. Explique comment les délégués travaillent dans le code suivant?
- 21. MPMoviePlayerController et le bouton suivant
- 22. Comment comprendre le code C++ suivant?
- 23. Pourquoi est-ce que je reçois une exception avec le code suivant?
- 24. pouvez-vous expliquer le code suivant
- 25. Fichier IO doute dans le code suivant
- 26. Le code Jquery ne fonctionne pas dans IE8. Que faire?
- 27. Comment implémenter GetExitCodeProcess dans le code suivant?
- 28. RECHERCHE SPHINX: searchd doit-il fonctionner en tant que service pour le faire fonctionner avec PHP?
- 29. Précédent et le bouton suivant
- 30. Convertir le code C# suivant en code java?
Est-ce ce devoir? – Patrick
Je suis d'accord avec Patrick, ça sent les devoirs. – Puppy
Ce ne sont pas les devoirs. J'essaie de comprendre, pourquoi il lance un comportement indéfini? – user373215