Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1571 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Pointeur de fonction membre sur fonction membre de meme classe

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Pointeur de fonction membre sur fonction membre de meme classe

n°967195
bb138
La vie est belle ...
Posté le 31-01-2005 à 19:07:26  profilanswer
 

Bonjour,
Je voudrais faire une chose comme ce qui suit mais j'ai un probleme et ne sait pas comment faire appel au pointeur sur fonction membre... Si vous avez une idee...

Code :
  1. class toto
  2. {
  3.    public :
  4.       toto( bool b ) {
  5.          if (b) d = &toto::disp1 ;
  6.          else d = &toto::disp2 ;
  7.       }
  8.       typedef void (toto::*D)() ;
  9.       D d ;
  10.    protected :
  11.       void disp1(void) { cout << "Disp1" << endl ; }
  12.       void disp2(void) { cout << "Disp2" << endl ; }
  13. } ;
  14. int
  15. main()
  16. {
  17.    toto t ;
  18.    (t.*d)() ;  // <-- probleme ici
  19.    return 0;
  20. }


mood
Publicité
Posté le 31-01-2005 à 19:07:26  profilanswer
 

n°967465
gatorette
Posté le 31-01-2005 à 22:50:54  profilanswer
 

boot::bind est ton amie dans ce cas (c'est peut être possible directement avec la STL mais je sais pas faire)
 
En gros ton problème est que dans ton initialisation de d, tu ne précise pas de quel objet est issue la fonction que tu souhaite appeler. Si ça peut t'aider ton truc marcherait bien avec des fonctions statiques mais il manque le pointeur this implicite dans ton cas.
 
Un code utilisant boost::bind et boost::function :

Code :
  1. #include <iostream>
  2. #include <boost/bind.hpp>
  3. #include <boost/function.hpp>
  4. using namespace std;
  5. class toto
  6. {
  7. public:
  8.   toto(bool b) {
  9.     if(b)
  10.       d = boost::bind(&toto::disp1,this);
  11.     else
  12.       d = boost::bind(&toto::disp2,this);
  13.   }
  14.  
  15. //  typedef void(*D)(void);
  16.   typedef boost::function<void(void)> D;
  17.   D d;
  18. protected:
  19.   void disp1() { cout << "Disp1" << endl; }
  20.   void disp2() { cout << "Disp2" << endl; }
  21. };
  22. int
  23. main()
  24. {
  25.   toto t(false);
  26.   (t.d)();
  27.   return 0;
  28. }


Message édité par gatorette le 31-01-2005 à 22:51:30

---------------
each day I don't die is cheating
n°967525
Taz
bisounours-codeur
Posté le 31-01-2005 à 23:10:15  profilanswer
 

boost, c'est génial.
 
Mais bon, faudrait déjà crriger l'exemple de base  
 
(t.*(t.d))() ;

n°967533
Taz
bisounours-codeur
Posté le 31-01-2005 à 23:12:00  profilanswer
 

pour en revenir à l'exemple de gatorette, tout l'intérêt, c'est ensuite de pouvoir écrire
 
  boost::function<void(void)> e = t.d;
 
  e();

n°967597
gatorette
Posté le 31-01-2005 à 23:30:42  profilanswer
 

Taz a écrit :

boost, c'est génial.


 :jap:  
 

Taz a écrit :


Mais bon, faudrait déjà crriger l'exemple de base  
 
(t.*(t.d))() ;


Et juste un t.d() comme dans mon exemple ? C'est incorrect ?
Parce que sur mon compilateur (VC++ 7.1) ça compile sans problème.


---------------
each day I don't die is cheating
n°967634
Taz
bisounours-codeur
Posté le 31-01-2005 à 23:39:15  profilanswer
 

c'est correcte. t.d est la fonction disp liée à l'instance t. On a ça dans plein de langage comme python par exemple. Je souligné juste que l'intérêt, c'est de pouvoir manipuler (t.d) comme un objet indépendant et en faire ce qu'on veut.

n°967856
gatorette
Posté le 01-02-2005 à 01:11:20  profilanswer
 

Taz a écrit :

c'est correcte. t.d est la fonction disp liée à l'instance t. On a ça dans plein de langage comme python par exemple. Je souligné juste que l'intérêt, c'est de pouvoir manipuler (t.d) comme un objet indépendant et en faire ce qu'on veut.


 :jap:  
 
OK... sinon j'ai essayé de faire ça en utilisant que la STL mais je n'ai pas réussi. Voici ce que j'ai fait jusqu'à présent :

Code :
  1. #include <iostream>
  2. #include <functional>
  3. using namespace std;
  4. class toto
  5. {
  6. public:
  7.   toto(bool b)
  8.     : d_(bind1st(mem_fun(&toto::disp1),this))
  9.   {
  10.     if(!b)
  11.       d_ = bind1st(mem_fun(&toto::disp2),this);
  12.   }
  13.   typedef binder1st<mem_fun1_t<void,toto,int> > D;
  14.   D d_;
  15. private:
  16.   void disp1(int) { cout << "disp_1" << endl; }
  17.   void disp2(int) { cout << "disp_2" << endl; }
  18. };
  19. int main()
  20. {
  21.   toto t(true);
  22.   t.d_(5);
  23.   return 0;
  24. }


 
Deux gros problèmes :  

  • J'ai été obligé de mettre un paramètre (int) à mes fonctions car sinon le bind1st (indispensable pour lier le this à la fonction) n'a pas assez d'arguments. En effet, il exécute une fonction "binaire" (mon mem_fun_t acceptant comme argument mon pointeur vers mon objet toto et le int que j'ai rajouté) en simulant une fonction "unaire". La solution serait-elle de refaire une classe bindsolearg qui permettrait de binder à la création de l'objet le seul argument de la fonction qui nous intéresse ?
  • Comme un binder1st n'a pas de constructeur par défaut (contrairement à boost::function par exemple), il faut que je l'initialise à la construction. Or je suis obligé de mettre une fonction membre de toto (à cause du mem_fun_t) et mon toto n'est pas encore complètement initialisé. VC++ me met même un warning lors de  la compilation mais le programme semble tourner.


-----------------
v2
Bon en écrivant le message j'ai réflechi un peu et voici une version qui corrige les deux problèmes évoqués ci-dessus :

Code :
  1. #include <iostream>
  2. #include <functional>
  3. using namespace std;
  4. template<typename Operation>
  5. class bindsolearg
  6. {
  7. public:
  8.   typedef typename Operation::result_type result_type;
  9.   bindsolearg()
  10.     : op(0)
  11.   { }
  12.   bindsolearg(const Operation & _Func, const typename Operation::argument_type& _Arg)
  13.     : op(_Func), val(_Arg)
  14.   { }
  15.   result_type operator()() const
  16.   {
  17.     op(val);
  18.   }
  19. protected:
  20.   Operation op;
  21.   typedef typename Operation::argument_type value;
  22.   value val;
  23. };
  24. template<class Operation, class Type>
  25. bindsolearg<Operation> bindarg(const Operation& _Func, const Type& _Arg)
  26. {
  27.   return bindsolearg<Operation>(_Func,_Arg);
  28. }
  29. class toto
  30. {
  31. public:
  32.   toto(bool b)
  33.   {
  34.     if(!b)
  35.       d_ = bindarg(mem_fun(&toto::disp2),this);
  36.     else
  37.       d_ = bindarg(mem_fun(&toto::disp1),this);
  38.   }
  39.   typedef bindsolearg<mem_fun_t<void,toto> > D;
  40.   D d_;
  41. public:
  42.   void disp1() { cout << "disp_1" << endl; }
  43.   void disp2() { cout << "disp_2" << endl; }
  44. };
  45. int main()
  46. {
  47.   toto t(true);
  48.   t.d_();
  49.   return 0;
  50. }


 
Donc cette version fonctionne à peu près correctement. A priori le seul "petit" souci est que mon objet functor peut ne pas être initialsé (en utilisant le constructeur par défaut) et donc si on appelle la fonction ça plante misérablement. Dans un sens on peut arguer que si l'objet n'est pas initialisé c'est qu'il y a un défaut de conception mais la méthode utilisée dans boost::function (exception générée) est beaucoup plus propre et exploitable.
 
Bon au final je pense qu'on peut conclure que Boost  :love:  est vraiment indispensable !


---------------
each day I don't die is cheating
n°967857
Taz
bisounours-codeur
Posté le 01-02-2005 à 01:14:48  profilanswer
 

Bonne conclusion. <functional> c'est pas mal au sein d'expression simple, comme par exemple en argument temporaire de std::copy. Dès qu'on veut aller plus loin, ou utiliser avec des fonctions (même membres) avec des paramètres variés, const, , références, etc, c'est l'enfer. Il y a d'ailleurs des défaillances de STL là dessus. D'où http://boost.org/libs/functional/index.html
 
Boost::function<> est vraiment très pratique.
 
 
edit: sinon c'est très bien. C'est exactement l'approche qu'il faut avoir.
 
J'ai un problème. J'essaie de les résoudre avec les outils que je maîtrise déjà. Je me rends compte que mes outils ne sont pas suffisants. J'essaie de fabriquer un nouvel outil plus puissant. Je touche du doigts la technologie nécessaire à résoudre mon problème. Je ne suis pas victime du NIH. J'utilise une implémentation populaire qui a fait ses preuves. Je maîtrise un nouvel outil.


Message édité par Taz le 01-02-2005 à 01:21:22
n°967925
bb138
La vie est belle ...
Posté le 01-02-2005 à 09:33:27  profilanswer
 

Merci a vous deux !
 
Merci Taz pour la correction :

Citation :

(t.*(t.d))() ;


et merci gatorette pour tes exemples explicites.
 
Je vais regarder cette boost d'un peu plus pres que ce que j'ai fait jusqu'a present.
@+
BB138

n°1738383
NounouRs
Non parce que c pas mon pied !
Posté le 28-05-2008 à 15:43:44  profilanswer
 

C'est peut etre un peut tard pour reouvrir ce post, mais j'ai une question tout à fait similaire, concernant boost::signal
 
je souhaite binder une methode membre (une callback) à un signal boost, par .connect  
Mais je ne parviens pas à lui passer le pointeur vers ma fonction comme il se doit.

mood
Publicité
Posté le 28-05-2008 à 15:43:44  profilanswer
 

n°1738479
IrmatDen
Posté le 28-05-2008 à 20:19:17  profilanswer
 

Exemple pour un signal de envoyant un float en paramètre:

Code :
  1. boost::signal<void (float)> sig;
  2. sig.connect(boost::bind(&LaClasse::UneFonction, instanceDeLaClasse, _1)); // où _1 correspond à l'argument qui sera transmis
  3. sig(3.14f);


Message édité par IrmatDen le 28-05-2008 à 20:19:41

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Pointeur de fonction membre sur fonction membre de meme classe

 

Sujets relatifs
[C] Warning sur pointeur de fonction avec scandir (résolu)[MFC/VC++] Problème de pointeur
Endianness issue : warning sur cast de pointeur ?[SQL/ADP] Appeler une fonction dans un Etat
Retour d'une fonction [DEBUTANT]ouvrir un formulaire en fonction d'une valeur
Probleme passage de paramètres et fonction includeFonction qui regroupe plusieurs valeurs
pointeur de fonction membre d'une classe[C++] Pointeur de fonction sur membre d'une classe
Plus de sujets relatifs à : Pointeur de fonction membre sur fonction membre de meme classe


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR