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 :

"Pure virtual function called" et destructeur virtuel


Sujet :

C++

Vue hybride

Seb des Monts "Pure virtual function... 10/09/2009, 01h05
JolyLoic C'est pour le moins imprécis.... 10/09/2009, 08h13
koala01 Salut, Visiblement, tu as... 10/09/2009, 08h14
Seb des Monts merci pour ces précisions.... 10/09/2009, 09h30
Médinoc Tout simplement quand elles... 10/09/2009, 10h10
Seb des Monts ha oui ! C'est ça d'analyser... 10/09/2009, 13h19
Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 74
    Par défaut "Pure virtual function called" et destructeur virtuel
    Bonjour,

    en vue d'éradiquer un petit problème de "Pure virtual function called" à l'exécution d'un programme, j'ai mis ça dans un moteur de recherche bien connu, et je suis tombé sur une info qui m'étonne un peu :

    le destructeur des classe filles appellent naturellement le destructeur de la classe mère. le problème c'est qu'avec un Mere* pointant vers une instance de Fille, l'appel du destructeur (par delete) se contente par défaut d'appeler le destructeur de Mere (normal). il faut donc rajouter le mécanisme d'indirection virtuel pour que ça soit le destructeur du type réel de l'objet pointé qui soit appelé
    Rassurez-moi, ceci est faux ? On peut bien faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class A
    {
       A(){}   
       virtual ~A(){}
    };
     
    class B : public A
    {
       B(): A(){}
       virtual ~B(){}
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void NettoyerTab()
    {
        int i =0, imax = Tab.size();
        for(i = 0; i < imax; ++i)
        {
            if(Tab[i]) != NULL)
            {
                delete ( Tab[i] );  
            }
        }
        Tab.clear();
    }

    Mon problème s'arrange en fait traquant les fonctions virtuelles pures dans les constructeurs et destructeurs.

    Je ne pense pas qu'il soit nécessaire de transtyper pour bien deleter, même dans le cas cité.
    Merci d'avance pour cette précision.

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    C'est pour le moins imprécis. Déjà, "rajouter le mécanisme d'indirection virtuel" signifie juste dans le texte déclarer le destructeur de la classe de base "virtual". Mais ce qui se passe si ce n'est pas fait, ce n'est pas simplement que le mauvais destructeur sera appelé, c'est un comportement indéfini qui peut avoir d'autres impacts (corruption mémoire...).

    Je ne vois pas de problèmes dans ton code.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,

    Visiblement, tu as mal lu ce qu'il dit:

    Si le destructeur de la classe mère n'est pas virtuel, le fait d'invoquer delete sur un pointeur vers le type de la classe mère n'appellera effectivement pas le destructeur de la classe enfant.

    Donc, ceci ne fonctionne pas:
    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
     
    class A
    {
        public:
            A(){cout<<"constructeur de A"<<endl;}
            ~A(){cout<<"destructeur de A"<<endl;}
    };
     
    class B: public A
    {
        public 
            B(){cout<<"constructeur de B"<<endl;}//s'il existe un constructeur
                                   // par défaut pour la classe mère, son appel est
                                   // implicite
            ~B(){cout<<"destructeur de B"<<endl;}
    };
    int main()
    {
        std::vector<A*> tab;
        for(int i=0;i<10;++i)
            tab.push_back(new B);
        for(int i=0;i<10;++i)
            delete tab[i];
        return 0;
    }
    Pour que le polymorphisme fonctionne, il faut que le destructeur de A soit déclaré virtuel (ce qui fera en sorte que celui de B le soit également de manière implicite, même s'il est préférable de l'indiquer explicitement )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 74
    Par défaut
    merci pour ces précisions.
    koala, tu as raison. J'aurai pu le comprendre autrement.
    Mais comme je ne vois pas de bonne raison pour ne pas avoir les destructeurs virtuels dans une hiérarchie de classes, ça m'a fait douter...
    merci

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 394
    Par défaut
    Citation Envoyé par Seb des Monts Voir le message
    Je ne vois pas de bonne raison pour ne pas avoir les destructeurs virtuels dans une hiérarchie de classes
    Tout simplement quand elles ne sont pas dédiées à un emploi polymorphique.

    GotW conseille d'avoir le destructeur de classe mère soit public et virtuel, soit protégé et non-virtuel (sachant qu'il conseille aussi de déclarer systématiquement les constructeurs de la classe mère comme protégés, et n'autoriser que l'instanciation des classes "feuilles").
    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 confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 74
    Par défaut
    ha oui !
    C'est ça d'analyser par le prisme de ses projets !

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Je me permet une légère digression sur le sujet (on scindera si nécessaire ), mais j'en viens presque à me demander si, dans de nombreux cas, on n'en arrive pas à envisager le polymporphisme comme tout à fait naturel, alors qu'il devrait être considéré, à l'instar des goto, de la récursivité et d'autres méthode, comme ne devant intervenir que lorsque c'est réellement nécessaire...

    Comprenez moi, ce n'est pas son utilité que je remets en cause, mais son usage.

    J'ai l'impression que l'on considère le polymorphisme comme aussi naturel que le fait de respirer ou d'avoir deux jambes, sans se rendre compte qu'il s'agit d'une technique qui représente malgré tout un cout non négligeable en terme de performances.

    J'ai l'impression que, dans bien des cas, on gères des collections de pointeurs dont le type est déclaré comme étant la classe de base pour "profiter du polymorphisme", alors qu'il serait largement plus intéressant de gérer les différents types d'objets sous la forme d'autant de collections qu'il n'y a de types réels...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

Discussions similaires

  1. Réponses: 9
    Dernier message: 02/04/2008, 10h05
  2. [pure virtual call] erreur d'execution
    Par ZaaN dans le forum C++
    Réponses: 9
    Dernier message: 22/02/2008, 17h32
  3. Réponses: 2
    Dernier message: 14/06/2007, 10h05
  4. Réponses: 4
    Dernier message: 17/05/2007, 16h47
  5. performances des virtual functions
    Par xxiemeciel dans le forum C++
    Réponses: 2
    Dernier message: 25/07/2005, 17h24

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