Fonctions membres et fonctions classiques en callback

Fonctions membres et fonctions classiques en callback - C++ - Programmation

Marsh Posté le 15-10-2007 à 14:30:07    

Bonjour,
avant toutes choses, je tiens à préciser que je ne suis pas un as en C++, loin de là... Alors sachez être indulgeant.

 

Bref, dans le cadre de la réalisation d'un projet perso j'aurai à mettre en place une class permettant l'appel de fonctions en cas de détection de collisions entre objets (mais on se fou un peu de la finalité de tout ça). J'ai lu qu'il était impossible d'utiliser des fonctions membres non static comme fonction de callback, et ça parait assez logique d'après la doc que j'ai lu. Cette même doc préconise aussi de passer une instance de la class à la méthode static, en remplacement d'un appel à une méthode non static.

 

Donc j'essais de mettre en oeuvre tout cela avec quelques test.
J'en arrive à quelque chose de fonctionnel avec le code suivant :

Code :
  1. #define NULL 0
  2. #include <iostream>
  3.  
  4. class A
  5. {
  6.     public:
  7.         void registerEvent( void (*callBackFunction)(void* i),void* instB=NULL)
  8.         {
  9.             callBackFunction(instB);
  10.         }
  11. };
  12.  
  13. class B
  14. {
  15.      public:
  16.          int i;
  17.          static void test(void *i)
  18.          {
  19.             B* b = (B*) i;
  20.              std::cout<< "Valeur de b->i : " << b->i << std::endl;
  21.          }
  22. };
  23.  
  24. int main()
  25. {
  26.     B* b = new B();
  27.     b->i = 100;
  28.     
  29.     A* a = new A();
  30.     a->registerEvent(&b->test,b);
  31.     
  32.     return 0;
  33. }
 

Cet exemple est censé afficher "La valeur de b->i est : 100", et c'est bien ce qu'il se passe.
Je n'ais donc pas vraiment de problème.

 

Ceci-dit, j'essais de faire quelque chose d'assez générique. C'est à dire pouvant aussi bien être utilisé avec une fonction membre static ou une fonction classique. D'où la présence de void* instB=NULL.

 

Mes questions :
Cela vous parait-il correctement construit? (Excepté l'absence de header)
Puis-je faire mieux?
J'ai lu (je ne sais plus où) qu'on pouvait simplifier l'écriture de tout ça avec un typedef, mais je ne vois pas trop comment... Pouvez-vous m'éclairer?

 

En vous remerciant par avance,
bonne journée!


Message édité par dwogsi le 17-10-2007 à 07:29:37

---------------
-- Debian -- Le système d'exploitation universel | Le gras c'est la vie! | /(bb|[^b]{2})/
Reply

Marsh Posté le 15-10-2007 à 14:30:07   

Reply

Marsh Posté le 15-10-2007 à 14:49:18    

sujet traiter 1000x, petite recherche sur le forum.
Pointer de fonction membre.
Y a même un "sujet utile" dessus

Reply

Marsh Posté le 15-10-2007 à 15:15:36    

J'ai déjà cherché sur le forum, ya bien des réponses sur "comment appeler les fonctions à partir d'un pointeur", mais ça ne me dit pas si vraiment j'ai fait les choses correctement. Sachant que je souhaite que ça fonctionne aussi bien pour des fonctions membres static que des fonctions classiques.

 

Je vais encore chercher, merci quand même.


Message édité par dwogsi le 15-10-2007 à 15:15:58

---------------
-- Debian -- Le système d'exploitation universel | Le gras c'est la vie! | /(bb|[^b]{2})/
Reply

Marsh Posté le 15-10-2007 à 15:23:44    

http://forum.hardware.fr/hfr/Progr [...] 3190_1.htm

 


Le truc c'est que pointeur de fonction membre et pointeur de fonction libre /  fonction membre statique sont incompatibles, mais les 2 existent


Message édité par Taz le 15-10-2007 à 15:23:55
Reply

Marsh Posté le 15-10-2007 à 15:44:31    

Merci pour le lien, je n'avais effectivement pas vu ce topic...
Sinon, pour le moment je me limite au pointeurs de fonctions membres statiques et fonction libres.
 
J'avais une petite idée pour utiliser les pointeurs de fonctions membre, mais c'est apparamment impossible à utiliser si on ne connaît pas d'avance le nom de la class à laquelle appartient la fonction en question? je me trompe?


---------------
-- Debian -- Le système d'exploitation universel | Le gras c'est la vie! | /(bb|[^b]{2})/
Reply

Marsh Posté le 15-10-2007 à 16:00:54    

Effectivement. T'as un exemple d'utilsation que tu voudrais ? y a plein de techniques genre objet-fonctions qui permettent de travailler correctement.

Reply

Marsh Posté le 15-10-2007 à 16:08:51    

En fait j'essais de me faire ma petite lib de gestion d'environnement en 2D, c'est plus expérimental qu'autre chose... Mais c'est assez instructif!

 

Ici j'aimerais pouvoir gérer les collisions d'objets. Donc quand on détecte une collision on appel une fonction (callback).

 

L'idée c'était de faire quelque chose d'assez générique, donc possibilité d'appeler une fonction membre statique ou non, ou encore une fonction libre.

 

Edit :
Ca donnerais une class qui stock un vecteur de structures contenant les infos sur une collision, et notamment la fonction a appeler en cas de collision.


Message édité par dwogsi le 15-10-2007 à 16:14:10

---------------
-- Debian -- Le système d'exploitation universel | Le gras c'est la vie! | /(bb|[^b]{2})/
Reply

Marsh Posté le 15-10-2007 à 16:21:49    

par exemple, avec une base virtuelle Callback tu peux tout faire:
- Callback* make(X (*f)(Z));
- Callback* make<T>(X (*T::f)(Z), T*);

Reply

Marsh Posté le 15-10-2007 à 17:13:28    

Pourrais-tu détailler juste un peu?
J'ai fais des recherches, testé plusieurs choses qui semblaient aller dans le sens de ce que tu propose... Mais rien qui ne fonctionne!


---------------
-- Debian -- Le système d'exploitation universel | Le gras c'est la vie! | /(bb|[^b]{2})/
Reply

Marsh Posté le 16-10-2007 à 16:21:10    

Code :
  1. template <typename RET, typename ARG>
  2. struct Callback
  3. {
  4. virtual RET call(ARG) = 0;
  5. virtual ~Callback() { }
  6. };
  7. template <typename RET, typename ARG>
  8. struct Free : Callback<RET, ARG>
  9. {
  10. RET (*f)(ARG);
  11. RET call(ARG a)
  12. { return f(a); }
  13. };
  14. template <typename RET, typename ARG, typename CLASS>
  15. struct Member : Callback<RET, ARG>
  16. {
  17. RET (CLASS::*f)(ARG);
  18. CLASS* that;
  19. RET call(ARG a)
  20. { return (that->*f)(a); }
  21. };
  22. template<typename RET, typename ARG>
  23. Callback<RET, ARG>* make(RET (*f)(ARG))
  24. {
  25. Free<RET, ARG> *cb = new Free<RET, ARG>();
  26. cb->f = f;
  27. return cb;
  28. }
  29. template<typename RET, typename ARG, typename CLASS>
  30. Callback<RET, ARG>* make(RET (CLASS::*f)(ARG), CLASS* that)
  31. {
  32. Member<RET, ARG, CLASS> *cb = new Member<RET, ARG, CLASS>();
  33. cb->f = f;
  34. cb->that = that;
  35. return cb;
  36. }
  37. struct Foo
  38. {
  39. static int foo(bool) { return 42; }
  40. int bar(bool) { return 69; }
  41. };
  42. int main()
  43. {
  44. Callback<int, bool> *cb = make(&Foo::foo);
  45. cb->call(false);
  46. delete cb;
  47. Foo f;
  48. cb = make(&Foo::bar, &f);
  49. cb->call(true);
  50. delete cb;
  51. }


 
 
ça c'est l'idée de base d'une implémentation. maintenant le mieux c'est vraiment d'utiliser boost::bind

Reply

Marsh Posté le 16-10-2007 à 16:21:10   

Reply

Marsh Posté le 16-10-2007 à 17:04:17    

Taz a écrit :

maintenant le mieux c'est vraiment d'utiliser boost::bind


Ba justement c'est ce que je me suis mis à utiliser au fil de mes lectures. Ca va quand même mieux.
Mais j'aime aussi connaître les solutions disons... de base! Donc ce que tu propose ici m'intéresse aussi, ça va me faire quelque chose à étudier et tester. Merci bien.


Message édité par dwogsi le 16-10-2007 à 17:05:08

---------------
-- Debian -- Le système d'exploitation universel | Le gras c'est la vie! | /(bb|[^b]{2})/
Reply

Marsh Posté le 16-10-2007 à 23:12:44    

Taz a écrit :

ça c'est l'idée de base d'une implémentation. maintenant le mieux c'est vraiment d'utiliser boost::bind


si seulement borland savait le gérer correctement...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed