peut on passer une methode en parametre ?

peut on passer une methode en parametre ? - C++ - Programmation

Marsh Posté le 15-01-2003 à 20:45:09    

par exemple je voudrais faire ça:
 
j'ai un type liste deja defini d'objet de type O.
 
liste<O> l;
 
O& cherche(int x, (aucune idée du type) fget )
{
O obj;
for(int i=1;i<=tailleliste;i++)
{
  obj=l[i];
  if (x==obj.fget()) {return obj;};
};
 
ça donnerait:
 
O* po= & l.cherche(5,getx());
 
Y a pas moyen de faire un truc dans le style ?

Reply

Marsh Posté le 15-01-2003 à 20:45:09   

Reply

Marsh Posté le 15-01-2003 à 20:51:49    

en C++Builder y a moyen mais ça n'a pas l'air standard du tout :D  
(pour émuler les procedure/function of object du Pascal)


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 15-01-2003 à 20:58:50    

avec des pointeurs de fonction membre, je dirais..
un truc du genre
 

Code :
  1. O& cherche(int x, void (O::* fget)())
  2. ...
  3.   if (x==((&obj)->fget)()) {...}

 
 
à tester..

Reply

Marsh Posté le 15-01-2003 à 21:04:30    

il est possible de passer une fonction en parametre..;mais men rappelle plus comment kon fait.. mais c possible :D
 
Par contre, une methode.. faut voir... peut etre oui.. peut etre non :p

Reply

Marsh Posté le 16-01-2003 à 05:10:46    

Ça devrait donner ça:

Code :
  1. O* liste::cherche(int x, int (liste::*pget)() ) const
  2. {
  3. for(int i=1 ; i<= tailleliste ; i++)
  4.  if ( x == (liste[i].*fget()) )
  5.   return &liste[i];
  6. return NULL; //chou blanc
  7. }
  8. liste<O> l;
  9. O* po= & l.cherche(5, &liste::getx); //obligé de répéter liste:: en argument.


 
Voici le prédicat générique:

Code :
  1. struct A{
  2. int i;
  3. int geti(){ return i;}
  4. };
  5. //vrai si le membre *pmem de l'objet obj vaut value
  6. template <
  7. typename T_Obj, //le type de l'objet
  8. typename T_Mem  //le type du membre de l'objet
  9. >
  10. bool mem_val_tester(
  11. const T_Mem& value //valeur de membre
  12. T_Mem T_Obj::*pmem, //pointeur de membre
  13. const T_Obj obj, //Objet
  14. ){
  15. return obj.*pmem == value;
  16. }
  17. //vrai si l'accesseur *pacc  de l'objet obj renvoie value
  18. template <
  19. typename T_Obj, //le type de l'objet
  20. typename T_Mem  //le type renvoyé par l'acesseur
  21. >
  22. bool acc_val_tester(
  23. const T_Mem& value //valeur de renvoi
  24. T_Mem (T_Obj::*pacc)(), //pointeur d'accesseur
  25. const T_Obj obj, //Objet
  26. ){
  27. return (obj.*pacc)() == value;
  28. }
Code :
  1. int main(){
  2. A a= {7};
  3. bool b1= mem_val_tester(7, &A::   i, a);
  4. bool b2= acc_val_tester(7, &A::geti, a);
  5. }

Il y a peut-être moyen de surcharger un même nom, mais mon compilateur n'en veut pas.
 
Si tu veux l'utiliser comme prédicat pour les algorithmes stl, démerde-toi.
(Il faut jouer avec des adaptateurs bind1st imbriqués, tu veux vraiment qu'on creuses ça ?)


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 16-01-2003 à 07:51:16    

je vais voir ça cet apres midi.
Sinon si ça peut generecisé mon code et m'eviter de faire une fonction de recherche par objet et par attribut ça m'arrangerait. :)

Reply

Marsh Posté le 16-01-2003 à 08:17:24    

wouatouwouatou a écrit :

il est possible de passer une fonction en parametre..;mais men rappelle plus comment kon fait.. mais c possible :D
 
Par contre, une methode.. faut voir... peut etre oui.. peut etre non :p

une methode, c'est aussi une fonction, donc tu la passes en pointeur et c'est regle ....


---------------
"OCPLB : On Casse Pas Le Binôme, 'moiselle Jade, Carlson & Peters, page 823 !"
Reply

Marsh Posté le 16-01-2003 à 09:30:28    

BotMan a écrit :

une methode, c'est aussi une fonction, donc tu la passes en pointeur et c'est regle ....


 
hum une méthode c'est une fonction qui a un param en plus : le pointeur vers l'objet auquel appartient la méthode (this)


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 17-01-2003 à 05:37:34    

Les pointeurs sur membres sont plus complexes: ils ont le double type de l'objet et du membre.
 
Allons-y:

Code :
  1. //patron de classe fonction prédicat unaire par membre (ouf)
  2. template <typename T_Obj,typename T_Mem>
  3. struct functor_mem_val_tester{
  4. T_Mem T_Obj::*pmem_; //pointeur de membre T_Mem dans un objet T_Obj
  5. T_Mem value_; //valeur à comparer
  6. functor_mem_val_tester( //construire avec...
  7.  T_Mem T_Obj::*pmem, //...le membre et...
  8.  const T_Mem& value) //... la valeur.
  9.  :pmem_ (pmem )
  10.  ,value_(value)
  11. {}
  12. bool operator()(const T_Obj& object){ //tester avec un objet
  13.  return object.*pmem_ == value_; //le test est ici !
  14. }
  15. };
  16. //patron de classe fonction prédicat unaire par accesseur (re-ouf)
  17. template <typename T_Obj,typename T_Mem>
  18. struct functor_acc_val_tester{
  19. T_Mem (T_Obj::*pacc_)(); //pointeur d'accesseur
  20. T_Mem value_; //valeur à comparer
  21. functor_acc_val_tester(T_Mem (T_Obj::*pacc)(), const T_Mem& value): //construire avec l'accesseur et la valeur
  22.                              pacc_ (pacc)  ,       value_(value)
  23. {}
  24. bool operator()(const T_Obj& object){
  25.  return (object.*pacc_)() == value_;
  26. }
  27. };


Exemple:

Code :
  1. #include <functional>
  2. using namespace std;
  3. int main(){
  4. A a= {7};
  5. bool b1= mem_val_tester(7, &A::   i, a);
  6. bool b2= acc_val_tester(7, &A::geti, a);
  7. //objets fonction comparant A::i à 7
  8. functor_mem_val_tester<A,int> mymemtest(&A::   i, 7); //par membre
  9. functor_acc_val_tester<A,int> myacctest(&A::geti, 7); //par accesseur
  10. //test simple
  11. bool b3= mymemtest(a);
  12. bool b4= myacctest(a);
  13. A array[5]= {1,2,3,4,5};
  14. //prédicat utilisé en stl
  15. A* pA1= find_if(&array[0], &array[5], mymemtest );
  16. A* pA2= find_if(&array[0], &array[5], myacctest );
  17. //mymemtest.pmem= &A::j; //possibilité de changer le membre testé
  18. //création du test sur place
  19. A* pA3= find_if(&array[0], &array[5], functor_mem_val_tester<A,int> (&A::   i, 7) );
  20. A* pA4= find_if(&array[0], &array[5], functor_acc_val_tester<A,int> (&A::geti, 7) );
  21. return 0;
  22. }


C'est quoi le prochain truc que tu vas demander :pt1cable: ?


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 22-01-2003 à 19:09:37    

J'ai du mal a comprendre cette notation :  T_Obj::*pmem

Reply

Marsh Posté le 22-01-2003 à 19:09:37   

Reply

Marsh Posté le 23-01-2003 à 05:26:55    

Les pointeurs de membre (on va dire pm) ne sont pas comme les autres pointeurs des adresses, ce sont des offset: distance entre le membre et le début de l'objet.
 
::* est l'opérateur utilisé pour déclarer un pm.
.* est l'opérateur utilisé pour suivre un pm

Code :
  1. T_Mem var; //variable du même type que le membre
  2. T_Mem *pvar; //pointeur sur une variable du même type que le membre
  3. T_Mem T_Obj::*pmem; //'pointeur' de membre de type T_Mem dans un objet T_Obj
  4. Obj.*pmem; //'indirection' d'un pm sur un objet


Mais pourquoi le type de l'objet fait-il partie du type du pm ?
C'est parce que les pm supportent le mécanisme virtuel.
Il leur est donc nécessaire de savoir à quel type d'objet ils s'appliquent, pour savoir s'il le virtuel s'applique, et si c'est le cas où se trouve le pointeur de table virtuelle (invisible).
 
C'est chaud tout ça... je n'ai compris que récemment.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 23-01-2003 à 05:49:09    

[:plat00n][:plat00n][:plat00n][:plat00n][:plat00n]


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 23-01-2003 à 09:57:09    

J'ai reussit a l'implementer et c'est vraiment supper pratique, ça m'arrange vraiment.
Par contre j'ai reussit a faire une fonction qui prend un membre en parametre, mais pas reussit a faire en sorte que cette même fonction appelle une autre fonction qui prend un membre en paramtre. (le même parametre en fait).
Je vois pas comment  faire passer le bidule.
 
J'aurais voulu que search member appelle test_member pour la comparaison, mais j'ai pas reussit.
Ce que je tente de faire va sans doute etre discuté par crtaines personnes, mais spa grave :D
J'ai du mal avec les const etc.
 

Code :
  1. template<class T_Obj,class T_Mem>
  2. bool test_member(T_Mem value,T_Mem (T_Obj::*pacc)(),T_Obj obj)
  3. {
  4.   return (obj.*pacc)()==value;
  5. };
  6. template<class T_Obj,class T_Mem>
  7. Plist<int> search_member(T_Mem value,T_Mem (T_Obj::*pacc)(),Plist<T_Obj> &l)
  8. {
  9.   Plist<int> r;
  10.   int n=l.getsize();
  11.   if (n>0)
  12.     {
  13.       Pnode<T_Obj>* f = l.getnode(1);
  14.       for(int i=1;i<=n;i++)
  15. {
  16.   if  ((f->getinfo()->*pacc)()==value)
  17.     {
  18.    
  19.       r.adde(new int (i));
  20.     };
  21.   f=f->getnext();
  22.  };
  23.     };
  24.   return r;
  25. };


Message édité par karim63 le 23-01-2003 à 09:59:58
Reply

Marsh Posté le 23-01-2003 à 10:00:50    

:sol:  :sol:  :sol:  :sol:  :D merci pour moi

Reply

Marsh Posté le 23-01-2003 à 10:20:37    

personne n'a palé des memfun?  
 
http://www.sgi.com/tech/stl/mem_fun_t.html
 
c'est plus simple à mon avis :hello:

Reply

Marsh Posté le 23-01-2003 à 11:10:05    

farib a écrit :

:sol:  :sol:  :sol:  :sol:  :D merci pour moi


C'etait pour la geniale clarification de Musaran precedent mon post.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 24-01-2003 à 09:03:24    


Si ça continues je vais y prendre goût.
Tu sais qu'on a droit à 10 smileys par post :o ?
 
Après réflexion je peut étoffer l'explication, on reprends:
????
Les pointeurs de membre (on va dire pm) ne sont pas comme les autres pointeurs des adresses, ce sont des offset: distance entre le membre et le début de l'objet.
 
Les opérateurs de membre:

Code :
  1. ::  //pour spécifier un membre
  2. ::* //pour déclarer un pm.
  3. .* //pour 'suivre' un pm sur un objet
  4. ->* //pour 'suivre' un pm sur/via un pointeur d'objet


Base de travail

Code :
  1. typedef int T_Mem;
  2. struct T_Obj{
  3. T_Mem mdat;                      //membre
  4. T_Mem mfun(){return this->mdat;} //accesseur
  5. };
  6. T_Obj Obj; //objet
  7. T_Mem var; //variable du même type que le membre


Exemple

Code :
  1. //pointeur classique
  2. T_Mem *pvar; //pointeur sur une variable du même type que le membre
  3. pvar= &var; //initialisé avec une adresse de variable n'importe où en mémoire
  4. *pvar; //suivre le pointeur, retrouve var
  5. //pointeur de membre de données
  6. T_Mem   T_Obj::*pmdat; //'pointeur' de membre de type T_Mem dans un objet T_Obj
  7. pmdat= &T_Obj::mdat; //initialisé avec un offset de membre dans T_Obj (ou parent) exclusivement
  8.           Obj.*pmdat; //'suivre' l'offset, retrouve mdat
  9. //pointeur de membre méthode
  10. T_Mem  (T_Obj::*pmfun)(); //'pointeur' de méthode renvoyant T_Mem dans un objet T_Obj
  11. pmfun= &T_Obj::mfun; //initialisé avec une adresse de fonction
  12.          (Obj.*pmfun)(); //'suivre' l'offset et appeler la méthode
  13. //Les mêmes mis en parallèle
  14. T_Mem         *pvar    = &var         ;      *pvar     ; //variable
  15. T_Mem  T_Obj::*pmdat   = &T_Obj::mdat ;  Obj.*pmdat    ; //membre de données
  16. T_Mem (T_Obj::*pmfun)()= &T_Obj::mfun ; (Obj.*pmfun)() ; //méthode. Parenthèses car .* est moins prioritaire que ()


Le pm ne se déréférence qu'associé avec un objet.
Normal: c'est un décalage sur quelque chose.
 
Mais pourquoi le type de l'objet fait-il partie du type du pm ?
1) La sécurité de type à la compilation.
Si on pouvait appliquer le pm à n'importe quel objet, il n'y aurait pas forcément le bon membre au bon offset.
 
2) Parce que les pm supportent le mécanisme virtuel.
Il leur est donc nécessaire de savoir à quel type d'objet ils s'appliquent, pour savoir s'il le virtuel a lieu, et si c'est le cas où se trouve le pointeur de table virtuelle (invisible).
 
Pour ces raisons, le pm méthode subit les contraintes d'un membre. Alors que c'est une adresse globale de fonction (comme un pointeur banal), puisque les fonctions ne sont pas physiquement dans l'objet.
????
 
C'est plus long mais mieux détaillé... c'est bon ou pas ?
 
 
karim63:

Code :
  1. if  ((f->getinfo()->*pacc)()==value)

À priori c'est comme ça:

Code :
  1. if ( test_member(value, pacc, *(f->getinfo()) ) )

Mais je teste pas.
 
 

++Taz a écrit a écrit :

personne n'a palé des memfun?



Je crois que c'est pas compatible avec ça:

Citation :

eviter de faire une fonction de recherche par objet et par attribut

Enfin je suis pas sûr là...
 
C'est de plus en plus [:ciler] ce qu'on fait ici.
 
Ah au fait, les "adaptateurs bind1st imbriqués" ne peuvent pas marcher directement, vu que ces adaptateurs ne manipulent que des fonctions à deux argument.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 24-01-2003 à 09:18:03    

Nous disons donc 10 smileys? voilà, voilà!
 
[:plat00n]  
[:plat00n][:plat00n]  
[:plat00n][:plat00n][:plat00n] [:plat00n]
[:plat00n][:plat00n]
[:plat00n]
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

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