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

Langage C++ Discussion :

apeller une fonction virtuelle depuis le desrtucteur


Sujet :

Langage C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    613
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 613
    Par défaut apeller une fonction virtuelle depuis le desrtucteur
    Salut

    Alors j'ai compris qu'on ne pouvait pas le faire, mais j'aimerai trouver un autre moyen.
    Je vous explique mon cas.

    J'ai une classe CThread de base qui s'ocupe de la création et destruction de threads.
    Une classe CExample qui en hérite.

    Le destructeur de Cthread attend la fin du thread, qui est en train de tourner dans une fonction de la classe CExample. Il fait un join sur le thread.
    J'aimerai pouvoir apeller dans ce destructeur une fonction OnStop(), virtuelle, qui est redéfinie dans CExample et qui permet de demander à mon thread de s'areter.

    Comme en C++, l'appel de la fonction virtuelle dans le destructeur de ma classe CThread n'apelle pas celle de la classe CExample, je suis obligé d'ecrire avant chaque delete cexample : cexample.OnStop().

    Y a t'il un autre moyen ?

    merci

  2. #2
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 551
    Par défaut
    Bonjour,

    c'est au destructeur de CExample d'appeler OnStop(), pas à celui de CThread
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    613
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 613
    Par défaut
    Ok.
    J'aurai du y penser, merci.
    Le petit inconvenient c'est qu'on doit l'ajouter dans chaque classe qui dérive de CThread, alors que ça aurait été pratique que ça fasse partie de l'implémentation de CThread justement de s'occuper de ça.

  4. #4
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 551
    Par défaut
    le problème c'est que comme vous l'aviez dit cela n'est pas possible car le destructeur de Cthread est appelé après le destructeur des classes filles

    il reste une autre solution : ne pas directement appeler delete sur les sous classes mais une autre opération définie sur Cthread et qui fera l'appel d'OnStop puis le delete.
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par bruno_pages Voir le message
    il reste une autre solution : ne pas directement appeler delete sur les sous classes mais une autre opération définie sur Cthread et qui fera l'appel d'OnStop puis le delete.
    Si j'interprète bien ce que tu propose, cela donnerait quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Cthread 
    {
        public: 
            virtual void onStop() = 0;
            void destroy()
            {
                onStop();
                delete *this;
            }
            /*...*/
    };
    Mais il y a alors un problème, du fait de l'appel de delete sur this:

    Si tu travailles avec un pointeur sur CThread, tu en arrivera à une situation dans laquelle ton pointeur semble toujours pointer vers une adresse valide, alors que la dite adresse a été invalidée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void foo(CThead * ptr)
    {
        /*...*/
        ptr->destroy(); // DANGER 
        /* y a d'autre choses à faire, on "oublie" que ptr a été détruit...*/
        ptr->machinChose(); //BOUM... ptr représente une adresse invalide
    }
    Si on travaille avec un objet, c'est encore pis: on cours tout droit vers une tentative de double destruction d'un objet:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void bar()
    {
        /*CExemple hérite de CThread ;-) */
        CExemple mt(/*parametres éventuels */);
        /* Tout va très bien, madame la marquise ...*/
        mt.destroy(); // CRACK : première destruction de l'objet
        /* éventuellement une ou deux choses à faire après */
    } // BOUM : destruction automatique de mt... qui a déjà été détruit :-P
    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

  6. #6
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 551
    Par défaut
    Bonjour,

    il est bien évident qu'appeler machinchose après destroy est absurde, mais ni plus ni moins qu'après delete

    bien-sur cela ne marche pas dans le cas d'une variable auto détruite, mais ni plus ni moins que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    {
      CExemple e;
      delete &e
    }
    cette solution n'était qu'un pi aller (je ne sais pas si cela s'écrit ainsi ), encore une fois la bonne solution est d'appeler OnStop dans le destructeur des sous classes
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    Bonjour,

    il est bien évident qu'appeler machinchose après destroy est absurde, mais ni plus ni moins qu'après delete
    Le code que j'ai présenté est, bien sur, absurde, mais il ne reflète que la partie visible de l'iceberg, dans le sens où l'appel de machinchose pourrait très bien survenir... dans une des fonctions appelante de foo, après appel de celle-ci...

    Cela met (une fois de plus ) en évidence le fait que la destruction d'un objet ne devrait être prise en charge que par... l'objet qui a la responsabilité explicite d'en gérer la durée de vie, et que, accessoirement, le comportement onStop ne devrait donc pas être "inclus" dans le destructeur
    bien-sur cela ne marche pas dans le cas d'une variable auto détruite, mais ni plus ni moins que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    {
      CExemple e;
      delete &e
    }
    Mais là, c'est l'erreur "de débutant" qui consiste à vouloir appeler un delete sur une variable qui n'a pas été créée avec new...

    Il est vrai que si le comportement appelé est... destroy, on peut, effectivement se douter qu'il... détruit la variable au départ de laquelle on l'appelle, mais si on choisit un nom de fonction moins explicite, on *court le risque* que la destruction de l'objet soit invoquée indument...

    Voilà qui plaide encore pour le fait de clairement séparer la gestion de onStop et... la destruction de l'objet
    cette solution n'était qu'un pi aller (je ne sais pas si cela s'écrit ainsi ), encore une fois la bonne solution est d'appeler OnStop dans le destructeur des sous classes
    (En fait, ca s'écrit avec un S "pis aller" (pis-->pire) comme l'indique la liaison effectuée lorsqu'on le prononce )

    Je ne crois pas...

    Je dirais plutôt qu'il faudrait prévoir d'invoquer onStop au moment où... l'exécution du thread s'arrête, c'est à dire, juste avant la fin de la fonction qui utilise le thread, après avoir supprimé les locks et autres mutexes.

    Après tout, rien n'indique a priori qu'un thread quel qu'il soit est actif au moment de sa destruction... Surtout s'il entre dans une collection d'objets polymorphes.

    Et comme il ne devrait pas pouvoir être détruit tant qu'il est actif, il n'y a a priori aucune raison de lui faire envoyer un signal de fin d'exécution juste avant la destruction (par contre, il peut être opportun de veiller à... ce qu'il ait fini de travailler avant d'accepter la destruction )
    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

  8. #8
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    {
      CExemple e;
      delete &e
    }
    Après le pis aller, un coq à l'âne si vous permettez
    Que se passe-t-il si on fait un truc comme ceci ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    {
      CExemple e;
      shared_ptr<CExemple> e_ptr(&e);
    }
    Il me semble que le problème est le même, le shared_ptr<> va tenter de faire un delete sur une adresse du stack lors de sa destruction.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par camboui Voir le message
    Il me semble que le problème est le même, le shared_ptr<> va tenter de faire un delete sur une adresse du stack lors de sa destruction.
    De prime abord, et en prenant donc tout le risque d'erreur que peut impliquer une réaction "à chaud", je dirais que tu serais confronté à un problème strictement identique
    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

  10. #10
    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
    Citation Envoyé par camboui Voir le message
    Après le pis aller, un coq à l'âne si vous permettez
    Que se passe-t-il si on fait un truc comme ceci ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    {
      CExemple e;
      shared_ptr<CExemple> e_ptr(&e);
    }
    Il me semble que le problème est le même, le shared_ptr<> va tenter de faire un delete sur une adresse du stack lors de sa destruction.
    Shared_ptr te permet de définir la façon dont va être détruite la variable qu'il maintient. (par défaut c'est delete qui est appelé).

  11. #11
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Je connais pas assez shared_ptr<> mais si on suppose qu'il soit possible de lui dire de ne pas détruire l'objet qu'il pointe, je doute quand même de la viabilité du code suivant lors du retour à la fonction appelante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    shared_ptr<CExemple> foo(){
      CExemple e;
      shared_ptr<CExemple> e_ptr(&e);
      e_ptr.is_on_stack();//assume this exists
      return e_ptr;
    }
    Mais bon, excusez l'intrusion, c'est juste parce qu'il y a un p'tit rapport avec le sujet que je demandais au passage.

  12. #12
    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
    Je faisais une remarque d'ordre générale sur la possibilité qu'offre shared_ptr. Pour un exemple concret regarde :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct null_deleter
    {
           void operator()(const void*) const {}
    };
     
    shared_ptr<T> T makeT()
    {
         static T t;
         shared_ptr<T> p(&t, null_deleter());
         return p;
    }
    exemple tiré de la doc. (à quelque chose prêt, je fais ça de tête).

  13. #13
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    613
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 613
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Et comme il ne devrait pas pouvoir être détruit tant qu'il est actif, il n'y a a priori aucune raison de lui faire envoyer un signal de fin d'exécution juste avant la destruction
    Non justement,
    J'ai fait cette classe pour me simplifier la vie, et j'ai volontairement inclu l'appel des mecanismes d'arret du thread dans le destructeur.

    Comme ca, lorsque je veux creer le thread je fait un new Cexample.

    Et lorsque je veux l'areter je fait un delete Cexample qui arrete le thread, attends sa fin, et le détruit.

    Apeller OnStop dans le destructeur des classes filles comme l'a suggéré bruno_pages semble une bonne idée.

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

Discussions similaires

  1. Réponses: 15
    Dernier message: 07/06/2010, 20h25
  2. Réponses: 2
    Dernier message: 05/03/2006, 19h29
  3. Faire apelle a une fonction javascript depuis un onclick=&am
    Par pierrot10 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 27/12/2005, 21h41
  4. [Info] Appeler une fonction Ada95 depuis Java
    Par mmathieu dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 15/09/2005, 09h42
  5. Comment appeler une fonction JavaScript depuis Delphi ?
    Par Alfred12 dans le forum Web & réseau
    Réponses: 4
    Dernier message: 17/06/2005, 18h15

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