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 :

héritage et destructeurs virtuels.


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut héritage et destructeurs virtuels.
    Bonjour,

    J'essaye de comprendre le fonctionnement de destructeurs virtuels.
    Si on considère une classe de base et une classe héritée de cette classe, alors il risque d'y avoir des problèmes si il n'y a pas de destructeurs virtuels.
    Je suis d'accord, cela semble logique.

    J'ai décidé de mettre en application ce qui est écrit, avec l'héritage suivant.

    Code : 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
     
    class TimeKepper{
    private:
    	int o;
    public:
    	TimeKepper(int u):o(u){};
    	   ~TimeKepper();
    };
    TimeKepper::~TimeKepper(){
    	cout<<"~TimeKepper()";
    }
     
    class AtomicClock:public TimeKepper{
    public:
       int k;
    public:
    	AtomicClock(int i,int j):TimeKepper(i),k(j){};
    	static AtomicClock* getAtomicClock();
    	~AtomicClock(){
    	cout<<"ee";
    	};
    };
     
    void main(){
     
     
     int *o;
    	AtomicClock  *pta=new AtomicClock(9,8);
    	{
    		TimeKepper  *ptkk=0;
    		o=&(pta->k);	
    		ptkk=pta;
     
    delete ptkk;
    	}
    }
    Normalement, ptkk ne devrait prendre en compte que la partie de base de l'objet pointé par pta.

    Quand on fait delete ptkk, celui-ci ne devrait détruire que la partie de base de l'objet pointé par pta, laissant dans la mémoire la partie héritée. Ce qui fait que l'on pourrait toujours avoir la valeur 8 via *o. Or, ceci n'est pas le cas, car malgré l'absence de destructeurs virtuels, on ne peut plus lire la valeur de *o après la destruction. Qu'il y ait destructeur virtuel ou non, cela ne change rien. Je ne comprends pas pq.


    (c'est pourtant exactement ce que fait scott meyers dans son livre pour
    illustrer ce risque).


    j'ai fait cela car je m'attendais, dans la mémoire, à ne trouver que 00 00 08, et pas 00 00 09 00 00 08 après le passage de delete

    Merci

  2. #2
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    voila d'ailleurs ce que dit scott meyers:


    There are lots of ways to keep track of time, so it would be reasonable to create a TimeKeeper base class along with derived classes for different approaches to timekeeping:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    class TimeKeeper {
     
    public:
     
      TimeKeeper();
     
      ~TimeKeeper();
     
      ...
     
    };
    class AtomicClock: public TimeKeeper { ... };
    class WaterClock: public TimeKeeper { ... };
    class WristWatch: public TimeKeeper { ... };

    Many clients will want access to the time without worrying about the details of how it's calculated, so a factory function — a function that returns a base class pointer to a newly-created derived class object — can be used to return a pointer to a timekeeping object:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    TimeKeeper* getTimeKeeper();       // returns a pointer to a dynamic-
     
                                       // ally allocated object of a class
     
                                       // derived from TimeKeeper
    In keeping with the conventions of factory functions, the objects returned by getTimeKeeper are on the heap, so to avoid leaking memory and other resources, it's important that each returned object be properly deleted:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    TimeKeeper *ptk = getTimeKeeper();  // get dynamically allocated object
                                        // from TimeKeeper hierarchy
    ..                                 // use it
    delete ptk;                        // release it to avoid resource leak

    . If getTimeKeeper were to return a pointer to an AtomicClock object, the AtomicClock part of the object (i.e., the data members declared in the AtomicClock class) would probably not be destroyed, nor would the AtomicClock destructor run. However, the base class part (i.e., the TimeKeeper part) typically would be destroyed, thus leading to a curious "partially destroyed" object. This is an excellent way to leak resources, corrupt data structures, and spend a lot of time with a debugger.

  3. #3
    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 : 33
    Localisation : Suisse

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

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Ton programme présente un comportement indéterminé car le destruteur de TimeKepper n'est pas virtuel.

    Ne cherche donc pas à déduire une loi générale, tu ne peux pas ^^ .
    Tu peux tomber sur le cas de l'objet à moitié détruit, mais pourquoi de celui de l'objet totalement détruit, tu ne peux pas prévoir.
    "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)

  4. #4
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Ton programme présente un comportement indéterminé car le destruteur de TimeKepper n'est pas virtuel.
    je sais bien. C'est justement ce que j'ai envie de faire. Mais dois-je en déduire que, bien que cela ne puisse pas se voir, il y a comportement indéterminé car il n'y a pas de destructeur virtuel.

    Dès qu'une classe est héritée d'une autre classe ==> destructeur virtuel??

  5. #5
    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 : 33
    Localisation : Suisse

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

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    je sais bien. C'est justement ce que j'ai envie de faire. Mais dois-je en déduire que, bien que cela ne puisse pas se voir, il y a comportement indéterminé car il n'y a pas de destructeur virtuel.
    Oui, c'est précisé dans la norme.
    Dès qu'une classe est héritée d'une PUBLIQUEMENT autre classe ==> destructeur virtuel??
    Oui. La FAQ contient une entré là dessus.

    Dans les cas des autres héritages, on peut pas upcaster (faire passer un objet de type dérivé pour un objet de type base, le problème, ne se pose donc pas)
    "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)

  6. #6
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Ou si il est non virtuel alors protected...

  7. #7
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    un destructeur protected??
    ca existe ca?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. probleme sur destructeur virtuel
    Par exhortae dans le forum C++
    Réponses: 5
    Dernier message: 01/03/2008, 07h32
  2. héritage et méthodes virtuelles ?
    Par Didine981 dans le forum C++
    Réponses: 4
    Dernier message: 08/12/2007, 13h43
  3. Destructeur virtuel et cascade
    Par buzzkaido dans le forum C++
    Réponses: 5
    Dernier message: 23/06/2007, 11h23
  4. Réponses: 16
    Dernier message: 21/05/2007, 01h04
  5. Exceptions, héritage et méthodes virtuelles
    Par Nuwanda dans le forum C++
    Réponses: 13
    Dernier message: 23/05/2006, 12h06

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