IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Delete d'une classe


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut Delete d'une classe
    Bonjour,

    J'ai une classe (disons A) qui contient plusieurs membres (dont d'autres classes, disons B et C). Lorsque je delete cette classe, la "bonne pratique" est de deleter également les autres classe comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A::~A()
    {  ~B(); ~C(); }
    Où de le faire de façon séparée et explicite, comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    A::~A() { }
    // puis, dans le main :
      ~A();
      ~B();
      ~C();
    Christian

  2. #2
    Membre averti Avatar de Trunks
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2004
    Messages
    534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2004
    Messages : 534
    Points : 412
    Points
    412
    Par défaut
    Ni l'un ni l'autre, les classes membres se delete d'elles-même lors de la destruction de la classe A.

    Un classe fait automatiquement appel au construction lors de la construction de celle-ci, et automatiquement appel au destructeur lors de sa destruction (appel à delete si construction avec new, ou dès la sortie de portée).

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Par contre, si ta classe contient un pointeur tout bête dont elle doit contrôler la durée de vie, il faut mettre explicitement delete dans le destructeur.

    Pour une classe non-copiable, c'est simple, mais pour une classe copiable, ça donne ceci:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    #include "B.h"
    #include <algorithm>
     
    class A
    {
    	B* pb;
    public:
    	A() : pb(new B())
    	{ }
     
    	A(A const & src) : pb(new B(*src.pb)) 
    	{ }
     
    	~A()
    	{
    		delete pb;
    	}
     
    	//Idiome copy-and-swap pour l'affectation
    	void Swap(A& right)
    	{
    		std::swap(pb, right.pb);
    	}
     
    	A& operator= (A tmp)
    	{
    		Swap(tmp);
    	}
    }
     
    namespace std {
    	template<>
    	inline void swap<A>(A& left, A& right)
    	{
    		left.Swap(right);
    	}
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut
    Trunks et Medinoc, merci pour votre réponse.
    Medinoc : dans ~A, tu deletes le pointeur vers B. Est-ce la pratique courante ? Quels sont les risques de ne pas le faire (fuite de mémoire, ...) ?
    Bien cordialement,
    Christian

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Dans mon exemple, on dit que la classe A gère la durée de vie de l'objet pointé par pb.
    Tu noteras que chaque copie pointe vers un nouvel objet de la classe B. Donc en effet, ne pas deleter pb cause une fuite de mémoire, ains qu'une fuite de toute ressource qui serait gérée par la classe B (comme un fichier ouvert, par exemple).

    Ce qui est important quand une classe gère la durée de vie d'un objet, ce sont quelques règles simples pour rendre la classe résistante aux exceptions:
    • Une classe donnée ne gère la durée de vie que d'une seule ressource. Si la classe gère deux ressources, encapsuler l'une de ces ressources dans une autre classe et l'inclure par valeur dans la classe principale.
    • Le destructeur doit libérer la ressource gérée, et ne doit pas lancer d'exception
      • Microsoft a bafoué cette politique dans Windows Communication Foundation, hélas.
    • Une classe qui gère une ressource doit soit être non-copiable, soit gérer la copie.
    • Si la copie est gérée et que la classe est modifiable, l'affectation se fait par l'idiome copy-and-swap
    • Même si la classe n'est pas copiable, il peut être recommandé qu'elle soit swappable.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre averti Avatar de Trunks
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2004
    Messages
    534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2004
    Messages : 534
    Points : 412
    Points
    412
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Une classe donnée ne gère la durée de vie que d'une seule ressource. Si la classe gère deux ressources, encapsuler l'une de ces ressources dans une autre classe et l'inclure par valeur dans la classe principale.
    Je ne savais pas Je suppose que c'est pour respecter le RAII et gérer correctement la destruction, notamment lorsqu'une exception se produit.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 89
    Points : 50
    Points
    50
    Par défaut Merci
    J'hésite parfois à poser les questions et lorsque je vois les qualités des réponses, je me dis que je fais bien de demander. Elles montrent aussi qu'il me reste encore des progrès à faire ... Merci à vous !

  8. #8
    Nouveau membre du Club
    Inscrit en
    Décembre 2006
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 31
    Points : 30
    Points
    30
    Par défaut appel de destructeur
    Même si un destructeur est une méthode a part entière d'une classe et tu as le droit de l'appeler directement, evite de le faire. Par contre, si tes classes attributs ont été créées par new, tu es obligé de le faire.

    Petit astuce:
    Quand ça vaut la peine, tu peux créer deux méthodes Build et Clean
    Build sera appelée par le constructeur mais tu pourra ultérieurement changer le contenu de ta classe

    ex: bool Build(...)
    {
    Clean();

    ....
    return true;
    }

    Clean sera appelée par le destructeur et tu pourra l'appeler également à ta guise pour nettoyer le contenu de ta classe..

    Citation Envoyé par coberle Voir le message
    Bonjour,

    J'ai une classe (disons A) qui contient plusieurs membres (dont d'autres classes, disons B et C). Lorsque je delete cette classe, la "bonne pratique" est de deleter également les autres classe comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A::~A()
    {  ~B(); ~C(); }
    Où de le faire de façon séparée et explicite, comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    A::~A() { }
    // puis, dans le main :
      ~A();
      ~B();
      ~C();
    Christian

  9. #9
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par alpidor Voir le message
    ...
    Petit astuce:
    Quand ça vaut la peine, tu peux créer deux méthodes Build et Clean
    Build sera appelée par le constructeur mais tu pourra ultérieurement changer le contenu de ta classe

    ex: bool Build(...)
    {
    Clean();

    ....
    return true;
    }

    Clean sera appelée par le destructeur et tu pourra l'appeler également à ta guise pour nettoyer le contenu de ta classe..
    C'est marrant, je les appelle Init() et Done(), ou bien Open() et Close(), ou bien Reset() et Clear() .

  10. #10
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Même si un destructeur est une méthode a part entière d'une classe et tu as le droit de l'appeler directement, evite de le faire. Par contre, si tes classes attributs ont été créées par new, tu es obligé de le faire.
    Non. le seul cas où le destructeur doit être appelé de manière manuelle est dans le cas d'un placement new.

    Sinon, il est soit automatiquement appelé lorsque qu'un objet alloué sur la pile passe hors de portée, soit via l'utilisation de delete (resp delete[]) pour des objets alloués par new (resp new[]).

    je n'ai pas la norme sous les yeux, mais je ne serai pas choquer qu'appeler explicitement le destructeur quand on ne doit pas le faire soit un comportement indéfini.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

Discussions similaires

  1. [tableau] Delete[] impossible sur tableau d'une classe
    Par EvaristeGaloisBis dans le forum Débuter
    Réponses: 4
    Dernier message: 10/02/2013, 12h45
  2. delete sur une classe predeclarer
    Par Moine dans le forum C++
    Réponses: 12
    Dernier message: 29/10/2009, 19h43
  3. Réponses: 5
    Dernier message: 12/06/2008, 00h52
  4. Variable d'une Classe Ancêtre
    Par Génie dans le forum Langage
    Réponses: 3
    Dernier message: 18/09/2002, 20h24
  5. Sortir un typedef d'une classe
    Par Theophil dans le forum C++Builder
    Réponses: 13
    Dernier message: 03/07/2002, 18h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo