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 :

Encore un pb de pointeur de fonction membre, solution "à la CBuilder" sous Visual ?


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 10
    Par défaut Encore un pb de pointeur de fonction membre, solution "à la CBuilder" sous Visual ?
    Bonjour,
    je suis en train de porter une application écrite en C++Builder en Visual C++,
    j'ai a peu près réussi à m'en sortir, mais j'ai le soucis suivant :
    Le code existant utilise pas mal d'appels vers des pointeurs de fonction membre,
    cela est possible sous C++Builder en utilisant le mot clef __closure,
    exemple (juste pour montrer la syntaxe) :
    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
     
    #include <string>
    #include <ostream>
    typedef void (__closure *TPointeurFonction)  (std::string const &msg);
     
    class CDummy
    {
    public:
       void  exemple (std::string const &msg) { std::cout << msg << "\r\n"; }
    };
     
    int main(int argc, char* argv[])
    {
       CDummy dummy;
       TPointeurFonction ptr = (&dummy.exemple);
       ptr ("hello");
       return 0;
    }
    existe-t-il une méthode aussi concise sous visual C++ pour faire cela ?
    j'ai pas mal recherché dans les FAQ et le forum, et les solutions tournent toujours autour de la même chose :
    * passer les fonctions en statiques ou en fonctions libres
    (je ne peux pas le faire)
    * utiliser boost (je ne veux pas le faire)
    * au lieu d'utiliser un pointeur de fonction membre:
    1- passer par une interface qui définit la fonction (virtuelle) à appeler
    2- remplacer le pointeur de fonction par un pointeur vers un objet de l'interface
    3- au lieu d'appeler le pointeur de fonction membre, on appelle la fonction virtuelle de l'objet interface ...

    dans tous les cas, les méthodes proposées me semblent induire énormément de modifications dans l'existant ....

    Quelqu'un aurait il une solution miracle, pas trop coûteuse ?
    Merci !

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    std::bind1st(&CDummy::exemple, &dummy) non ?
    Je dois avouer que je n'utilise que std::tr1::bind, personnellement, donc je connais pas bien ces reliques du passé...

  3. #3
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 502
    Par défaut
    "__closure" est vraisemblablement une MACRO de C++Builder.
    Je commencerais par voir le "code" de cette MACRO.

  4. #4
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    loufoque t'a presque donné la solution...
    Une fonction membre d'une classe porte toujours implicitement l'instance de la classe en cours.
    Donc tu vas devoir faire un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::tr1::bind(&MaClasse::fonction, this);
    ou bien un std::mem_fun(). Tu pourras trouver tout ce que tu veux dans le tuto de r0d

    Bonne continuation,

    Poukill

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 10
    Par défaut
    Je crois avoir à peu près compris le principe de l'approche suggérée.

    Elle nécessite néanmoins la connaissance de la classe associée à l'objet
    dont on prend le pointeur de fonction membre ...
    Dans mon cas, malheureusement, je ne vois pas trop comment l'adapter :

    j'ai une pléthore de classes qui utilisent des pointeurs de type closure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    typedef void (__closure *TPointeurA)  (int status, char const*msg);
    typedef void (__closure *TPointeurB)  (int a, int b, int c, int d, int e);
    typedef void (__closure *TPointeurC)  (char *msg, ...);
    etc.
    par ailleurs dans les classes, jamais je ne connais la classe sous-jacente
    au pointeur de fonction membre ...elles sont du type :

    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
     
    class CToto
    {
       TPointeurB  m_ptr;
    public:
            .........................
            .........................
     
       // Fixe le pointeur de fonction membre
       void  setPointeur (TPointeurB  ptr) { m_ptr = ptr; }
     
       // Un exemple d'appel
       void  doTheCall (void)
       {
          // A ce niveau, je connais la "forme" de la fonction :
          // renvoie void, et prend les arguments  (int, int, int, int, int)
          // je connais aussi implicitement l'objet sous jacent grace au mot-clef __closure,
          // mais je ne connais rien sur la classe, elle peut être absolument quelconque ...
          // à part qu'elle a une méthode non statique de type TPointeurB ...
          if (m_ptr != NULL)
            m_ptr (1, 2, 3, 4, 5);
       }
    }
    J'ai l'impression que l'utilisation de la stl / boost ou tr1 va m'obliger à
    modifier tout mon code, alors que ce que j'aimerais faire, c'est simplement
    trouver une astuce avec le minimum d'impact, pour lier mon pointeur avec
    l'objet et pouvoir appeler la méthode de l'objet.
    En fait, je ne recherche pas forcément une solution élégante et consise d'un
    point de vue théorique, mais plutôt, une solution qui marche, en modifiant
    au minimum l'existant (quitte à faire des C-cast foireux ...) !

    J'ai recherché sur le net, le mot clef __closure semble être intégré
    dans le compilateur lui même et n'est pas une macro ...
    cf. http://dn.codegear.com/article/20298
    jwiegley The ANSI standard allows the compiler to define new keywords beginning with __.
    Therefore, it is not a violation of the standard to process the __closure name when -A is on. However, I think I know what you're after. You can try defining a macro that turns __closure into white space, as one approach.
    merci pour les pistes !

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 10
    Par défaut
    Bon, au cas où cela intéresserait quelqu'un, finalement, la solution la moins pire que j'ai trouvée, en terme d'impact sur l'existant, est de passer par des classes d'interfaces et de remplacer les pointeurs de fonction membre par des pointeurs vers des objets implémentant l'interface :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    // à la place (ou en plus) du 
    typedef void (__closure *TPointeurFonction)  (std::string const &msg);
     
    // je déclare
    class InterfacePointeurFonctionExemple
    {
       virtual void exemple (std::string const&msg) = 0;
    };
    puis au lieu (ou en plus) du pointeur de fonction membre, je stocke une instance d'un objet implémentant cette interface :

    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
     
    // Par exemple je veux appeler la méthode exemple
    class CDummy : public  InterfacePointeurFonctionExemple
    {
    public:
       virtual void  exemple (std::string const &msg) { std::cout << msg << "\r\n"; }
    };
     
     
    int main(int argc, char* argv[])
    {
      CDummy dum;
     
      // A ce niveau je ne fait pas d'hypothese sur dum a part que cet objet
      // implemente InterfacePointeurFonctionExemple
      InterfacePointeurFonction *obj = &dum;
     
      obj->exemple ("hello");
    }
    Grosso modo, le coût est :
    1) définir les interfaces (il n'y en n'a pas énormément de différentes dans mon cas), c'est pas trop long ...
    2) ajouter l'héritage des interfaces dans les classes, on doit passer en revue chaque classe, mais il suffit d'ajouter :
    public InterfaceXXX à chaque fois, ce qui n'est pas trop dur ...
    (merci l'héritage multiple!)
    3) contrôler le nom de la méthode à appeler (là c'est un peu plus pénible, si son nom ne matche pas le nom de la méthode dans l'interface, car il faut soit renommer, soit recréer une classe d'interface, ou encore faire une méthode wrappeuse) ...
    4) vérifier qu'elle est bien virtuelle ou que le changement en virtuelle ne modifie pas la logique (là cela peut être éventuellement pénible si le code est pointu ou compliqué en terme d'héritage ...)

    Je n'ai finalement pas trouvé de macro miracle, mais en tout cas, cela marche!

Discussions similaires

  1. Pointeur sur fonction membre avec parametre
    Par Glosialabolas dans le forum C++
    Réponses: 7
    Dernier message: 06/02/2006, 02h32
  2. Pointeur de fonction membre.
    Par fabone dans le forum C++
    Réponses: 2
    Dernier message: 18/01/2006, 13h18
  3. Pointeur de fonction membre
    Par legend666 dans le forum C++
    Réponses: 1
    Dernier message: 04/10/2005, 20h46
  4. Réponses: 10
    Dernier message: 03/02/2005, 13h09
  5. Réponses: 5
    Dernier message: 12/01/2005, 20h58

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