OVH Cloud OVH Cloud

re : tableau de pointeurs de fonctions

11 réponses
Avatar
sentenza
slt,

Pr ne pas utiliser des if () else if() ... j'ai besoin d'utiliser un
tableau de pointeur de fonction.
Comment fait ton pour construir un tableau de pointeur de fonction qui
pointe vers des methodes d'une classe ?

ce que j'ai essaye de faire, mais sans succes :

template<typename T>
class MaClass
{
private:
std::auto_ptr< Container<T> > m_container;
public:
explicit MaClass(std::list<T> * stlContainer)
:m_container(new StlAdaptor< std::list<T> >(stlContainer)){ }

explicit MaClass(std::set<T> * stlContainer)
:m_container(new StlAdaptorSet< std::set<T> >(stlContainer)){ }

explicit MaClass(std::vector<T> * stlContainer)
:m_container(new StlAdaptor< std::vector<T> >(stlContainer)){ }

void Add(const T & value) { m_container->Add(value); }
void Sub(const T & value) { m_container->Sub(value); }
void Pop() { m_container->Pop(); }
};

struct t_functab
{
char *str;
void (MaClass::*f)();
};

t_functab functab[] = {
{"Add", MaClass::Add},
{"Sub", MaClass::Sub},
{"Pop", MaClass::Pop},
{0, 0};
};

c'est surement pas comme ca que l'on fait mais je n'ai trouve aucuns
renseignements dans mes docs :/

desole avec mes questions bizard, mais je debute en c++ et la syntax
n'est pas toujours evidente ...

--
char sentenza9[] =
"\xeb\x0d\x5f\x31\xc0\x50\x89\xe2"
"\x52\x57\x54\xb0\x3b\xcd\x80\xe8"
"\xee\xff\xff\xff/bin/sh";

10 réponses

1 2
Avatar
Le Géant Vert
"sentenza" a écrit dans le message de news:
3fd5d94d$0$6970$
slt,

Pr ne pas utiliser des if () else if() ... j'ai besoin d'utiliser un
tableau de pointeur de fonction.
Comment fait ton pour construir un tableau de pointeur de fonction qui
pointe vers des methodes d'une classe ?


un pointeur vers une méthode d'une classe est préfixée par le nom de cette
classe, autrement dit, une méthode de proto void m(void) dans une classe A
et une autre dans une classe B sont considérées de types DIFFERENTS,
respectivement :

void A::*(void), et :
void B::*(void)

donc tu vas avoir du mal à mixer plusieurs pointeurs de méthodes dans une
meme structure de données... à moins d'encapsuler tes pointeurs dans des SD
génériques et de retenir des infos les concernants pour les caster
joyeusement au moment opportun, mais là ca devient super tordu...

à mon humble avis, éviter des if() else if() en C++ peut se concevoir comme
du polymorphisme, avec un bon design de classes (et par ex des DP stratégy),
ça doit pouvoir se faire de manière transparente. L'idée de "collectionner"
des pointeurs sur méthodes, ça me fait un peu penser à vouloir
court-circuiter les mécanismes objet du langage.

Avatar
sentenza
Le Géant Vert wrote:
"sentenza" a écrit dans le message de news:
3fd5d94d$0$6970$

slt,

Pr ne pas utiliser des if () else if() ... j'ai besoin d'utiliser un
tableau de pointeur de fonction.
Comment fait ton pour construir un tableau de pointeur de fonction qui
pointe vers des methodes d'une classe ?



un pointeur vers une méthode d'une classe est préfixée par le nom de cette
classe, autrement dit, une méthode de proto void m(void) dans une classe A
et une autre dans une classe B sont considérées de types DIFFERENTS,
respectivement :

void A::*(void), et :
void B::*(void)

donc tu vas avoir du mal à mixer plusieurs pointeurs de méthodes dans une
meme structure de données... à moins d'encapsuler tes pointeurs dans des SD
génériques et de retenir des infos les concernants pour les caster
joyeusement au moment opportun, mais là ca devient super tordu...

à mon humble avis, éviter des if() else if() en C++ peut se concevoir comme
du polymorphisme, avec un bon design de classes (et par ex des DP stratégy),
ça doit pouvoir se faire de manière transparente. L'idée de "collectionner"
des pointeurs sur méthodes, ça me fait un peu penser à vouloir
court-circuiter les mécanismes objet du langage.




ouais c'est clair que c'est brutal comme methode, mais c'est les
consignes de mon proj, et a mon avis c'est pour nous obliger a manier
toutes les fonctionalitees du c++ :/

La je n'ai plus de cheveux a force de me les arracher :-P

--
char sentenza9[] "xebx0dx5fx31xc0x50x89xe2"
"x52x57x54xb0x3bxcdx80xe8"
"xeexffxffxff/bin/sh";


Avatar
sentenza
Le Géant Vert wrote:
"sentenza" a écrit dans le message de news:
3fd5d94d$0$6970$

slt,

Pr ne pas utiliser des if () else if() ... j'ai besoin d'utiliser un
tableau de pointeur de fonction.
Comment fait ton pour construir un tableau de pointeur de fonction qui
pointe vers des methodes d'une classe ?



un pointeur vers une méthode d'une classe est préfixée par le nom de cette
classe, autrement dit, une méthode de proto void m(void) dans une classe A
et une autre dans une classe B sont considérées de types DIFFERENTS,
respectivement :

void A::*(void), et :
void B::*(void)

donc tu vas avoir du mal à mixer plusieurs pointeurs de méthodes dans une
meme structure de données... à moins d'encapsuler tes pointeurs dans des SD
génériques et de retenir des infos les concernants pour les caster
joyeusement au moment opportun, mais là ca devient super tordu...

à mon humble avis, éviter des if() else if() en C++ peut se concevoir comme
du polymorphisme, avec un bon design de classes (et par ex des DP stratégy),
ça doit pouvoir se faire de manière transparente. L'idée de "collectionner"
des pointeurs sur méthodes, ça me fait un peu penser à vouloir
court-circuiter les mécanismes objet du langage.




pfff .. j'ai encore une erreur de compile .. je suppose que tu m'as
montre la facon de faire pour une class simple, mais moi c'est une class
template que j'utilise qui est prototypee comme ceci :


template <template <typename> class C, typename E>
class VM
{
....
void Push(char*);
};

et mon tableau de pointeur sur fonction comme ca :

typedef void (VM::*f1)();
typedef void (VM::*f2)(char*);

struct t_filefunc
{
char *name;
f1 func;
f2 funcarg;
};

t_filefunc functab[] = {
{"push", 0, VM::Push},
{0, 0} };

le compilo me pond cette erreur : parse error before `::' et ca survient
a la declaration des typedef ...

je suppose que c'est surement a cause du template, mais je ne vois pas
comment faire :/
--
char sentenza9[] "xebx0dx5fx31xc0x50x89xe2"
"x52x57x54xb0x3bxcdx80xe8"
"xeexffxffxff/bin/sh";


Avatar
Le Géant Vert
"sentenza" a écrit dans le message de news:
3fd63a71$0$6982$
Le Géant Vert wrote:
"sentenza" a écrit dans le message de news:
3fd5d94d$0$6970$

slt,

Pr ne pas utiliser des if () else if() ... j'ai besoin d'utiliser un
tableau de pointeur de fonction.
Comment fait ton pour construir un tableau de pointeur de fonction qui
pointe vers des methodes d'une classe ?



un pointeur vers une méthode d'une classe est préfixée par le nom de
cette


classe, autrement dit, une méthode de proto void m(void) dans une classe
A


et une autre dans une classe B sont considérées de types DIFFERENTS,
respectivement :

void A::*(void), et :
void B::*(void)

donc tu vas avoir du mal à mixer plusieurs pointeurs de méthodes dans
une


meme structure de données... à moins d'encapsuler tes pointeurs dans des
SD


génériques et de retenir des infos les concernants pour les caster
joyeusement au moment opportun, mais là ca devient super tordu...

à mon humble avis, éviter des if() else if() en C++ peut se concevoir
comme


du polymorphisme, avec un bon design de classes (et par ex des DP
stratégy),


ça doit pouvoir se faire de manière transparente. L'idée de
"collectionner"


des pointeurs sur méthodes, ça me fait un peu penser à vouloir
court-circuiter les mécanismes objet du langage.




pfff .. j'ai encore une erreur de compile .. je suppose que tu m'as
montre la facon de faire pour une class simple, mais moi c'est une class
template que j'utilise qui est prototypee comme ceci :


template <template <typename> class C, typename E>
class VM
{
....
void Push(char*);
};

et mon tableau de pointeur sur fonction comme ca :

typedef void (VM::*f1)();
typedef void (VM::*f2)(char*);

struct t_filefunc
{
char *name;
f1 func;
f2 funcarg;
};

t_filefunc functab[] = {
{"push", 0, VM::Push},
{0, 0} };

le compilo me pond cette erreur : parse error before `::' et ca survient
a la declaration des typedef ...

je suppose que c'est surement a cause du template, mais je ne vois pas
comment faire :/
--
char sentenza9[] > "xebx0dx5fx31xc0x50x89xe2"
"x52x57x54xb0x3bxcdx80xe8"
"xeexffxffxff/bin/sh";



vi, c'est norma que ça pose un problème.
ex, ce code compile :

template <class T>

class VM

{

public:

void push(char*);

};

template<class T>

void VM<T>::push(char *)

{

}

void (VM<int>::*ptr)(char *) = VM<int>::push;

typedef void (VM<int>::*f1)();

typedef void (VM<int>::*f2)(char*);

struct t_filefunc

{

char *name;

f1 func;

f2 funcarg;

};

void main(void)

{

}

note bien que la seule différence intéressante, c'est d'avoir préciser les
paramètres templates de f1 et f2 ; en effet, pour déclarer tes pointeurs sur
fonctions (ou les typedefs) , il faut le type complet ; donc, chose
importante :

un

void (VM<int>::*)() et un

void (VM<double>::*)()

sont de types DIFFERENTS et ne pourront pas se mixer au sein d'une meme
structure de données :/ peut-etre une piste à explorer : faire une structure
de données template pour contenir les pointeurs sur méthodes ? ... :-?



peut etre qu'en nous donnant le contexte et ce qui est demandé on arriverait
mieux à t'aider



Avatar
Loïc Joly
Le Géant Vert wrote:


un pointeur vers une méthode d'une classe est préfixée par le nom de cette
classe, autrement dit, une méthode de proto void m(void) dans une classe A
et une autre dans une classe B sont considérées de types DIFFERENTS,
respectivement :

void A::*(void), et :
void B::*(void)

donc tu vas avoir du mal à mixer plusieurs pointeurs de méthodes dans une
meme structure de données... à moins d'encapsuler tes pointeurs dans des SD
génériques et de retenir des infos les concernants pour les caster
joyeusement au moment opportun, mais là ca devient super tordu...


Il y a des choses pour simplifier ça. Par exemple boost::function et
boost::bind sur www.boost.org.

--
Loïc

Avatar
Le Géant Vert
Il y a des choses pour simplifier ça. Par exemple boost::function et
boost::bind sur www.boost.org.


sûr, mais si c'est donné à titre d'exercice, je pense qu'on attend du code
intégralement personnel, et pas le recours à une API extérieure ; à préciser
cela dit

Avatar
kanze
sentenza wrote in message
news:<3fd5d94d$0$6970$...

Pr ne pas utiliser des if () else if() ... j'ai besoin d'utiliser un
tableau de pointeur de fonction.
Comment fait ton pour construir un tableau de pointeur de fonction qui
pointe vers des methodes d'une classe ?

ce que j'ai essaye de faire, mais sans succes :

template<typename T>
class MaClass
{
private:
std::auto_ptr< Container<T> > m_container;
public:
explicit MaClass(std::list<T> * stlContainer)
:m_container(new StlAdaptor< std::list<T> >(stlContainer)){ }

explicit MaClass(std::set<T> * stlContainer)
:m_container(new StlAdaptorSet< std::set<T> >(stlContainer)){ }

explicit MaClass(std::vector<T> * stlContainer)
:m_container(new StlAdaptor< std::vector<T> >(stlContainer)){ }

void Add(const T & value) { m_container->Add(value); }
void Sub(const T & value) { m_container->Sub(value); }
void Pop() { m_container->Pop(); }
};

struct t_functab
{
char *str;
void (MaClass::*f)();
};

t_functab functab[] = {
{"Add", MaClass::Add},
{"Sub", MaClass::Sub},
{"Pop", MaClass::Pop},
{0, 0};
};

c'est surement pas comme ca


C'est prèsque ça. Pour prendre l'adresse d'une fonction membre, il faut
l'opérateur &, donc :

t_functab functab[] = P
{ "Add", &MaClass::Add },
// ...

D'autres problèmes :

- Le template. MaClass n'est pas une classe, mais le template d'une
classe. Pour prendre l'adresse d'une fonction membre, il faut avoir
une classe. Alors, selon la contexte :

. Dans le template, il n'y a pas de problème. Les pointeurs ne
seront créés réelement que lors de l'instantiation, et à
l'intérieur du template, MaClass est toujours interprété comme
MaClass<T>.

. Ailleurs, il faudrait bien que tu précises l'instantiation, par
exemple :

void (MaClass<int>::*f)( int& ) = &MaClass<int>::Add ;

- Il faut que toutes les fonctions aient la même signature : tu ne
peux pas initialiser un « void (MaClass::*)() » avec &MaClass::Add,
parce que &MaClass::Add a le type « void (MaClass::*)( T& ) ». La
raison en est simple : comment est-ce que tu compte utiliser le
pointeur ? Si tu as :
void (MaClass<int>::*f)() = &MaClass<int>::Pop ;
il faut écrire :
(p->*f)() ;
sans paramètre. Si tu as :
void (MaClass<int>::*f)( int& ) = &MaClass<int>::Add ;
il faut écrire :
(p->*f)( 42 ) ;

Enfin, en passant, les fonctions Add et Sub ne doivent-elles pas prendre
plutôt un « T const& » comme paramètre ?

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Avatar
Benoit Rousseau
wrote:
sentenza wrote in message
news:<3fd5d94d$0$6970$...
template<typename T>
class MaClass
{
[...]


}


- Il faut que toutes les fonctions aient la même signature : tu ne
peux pas initialiser un « void (MaClass::*)() » avec &MaClass::Add,
parce que &MaClass::Add a le type « void (MaClass::*)( T& ) ». La
raison en est simple : comment est-ce que tu compte utiliser le
pointeur ? Si tu as :
void (MaClass<int>::*f)() = &MaClass<int>::Pop ;
il faut écrire :
(p->*f)() ;
sans paramètre. Si tu as :
void (MaClass<int>::*f)( int& ) = &MaClass<int>::Add ;
il faut écrire :
(p->*f)( 42 ) ;


Ca marche ça ? Il me semble avoir lu qu'on ne pouvait appeler que les
membres statiques de cette façon.


--
--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/


Avatar
Le Géant Vert
"Benoit Rousseau" a écrit dans le message de news:
3fd6e74f$0$300$
wrote:
sentenza wrote in message
news:<3fd5d94d$0$6970$...
template<typename T>
class MaClass
{
[...]


}


- Il faut que toutes les fonctions aient la même signature : tu ne
peux pas initialiser un « void (MaClass::*)() » avec &MaClass::Add,
parce que &MaClass::Add a le type « void (MaClass::*)( T& ) ». La
raison en est simple : comment est-ce que tu compte utiliser le
pointeur ? Si tu as :
void (MaClass<int>::*f)() = &MaClass<int>::Pop ;
il faut écrire :
(p->*f)() ;
sans paramètre. Si tu as :
void (MaClass<int>::*f)( int& ) = &MaClass<int>::Add ;
il faut écrire :
(p->*f)( 42 ) ;


Ca marche ça ? Il me semble avoir lu qu'on ne pouvait appeler que les
membres statiques de cette façon.



m'est avis que si la méthode était statique, on pourrait se contenter d'un :
(*f)(42);

hors là on fait bien un :
(p->*f)(42)

ce qui signifie que p est un pointeur vers un MaClass<int>, et fourni donc
le contexte indispensable à l'éxécution de la méthode non statique.



Avatar
kanze
Benoit Rousseau wrote in message
news:<3fd6e74f$0$300$...
wrote:
sentenza wrote in message
news:<3fd5d94d$0$6970$...
template<typename T>
class MaClass
{
[...]


}


- Il faut que toutes les fonctions aient la même signature : tu ne
peux pas initialiser un « void (MaClass::*)() » avec &MaClass::Add,
parce que &MaClass::Add a le type « void (MaClass::*)( T& ) ». La
raison en est simple : comment est-ce que tu compte utiliser le
pointeur ? Si tu as :
void (MaClass<int>::*f)() = &MaClass<int>::Pop ;
il faut écrire :
(p->*f)() ;
sans paramètre. Si tu as :
void (MaClass<int>::*f)( int& ) = &MaClass<int>::Add ;
il faut écrire :
(p->*f)( 42 ) ;


Ca marche ça ?


Bien sûr. Je m'en suis déjà servi, et je n'ai jamais rencontré un
compilateur qui le rejette. (En revanche, j'ai une tendance à l'éviter
aujourd'hui, parce que j'ai trouvé pas mal de collègues qui le
rejettent.)

Il me semble avoir lu qu'on ne pouvait appeler que les membres
statiques de cette façon.


Au contraire : je ne crois pas que tu puisse appeler un membre statique
de cette façon. (À vérifier -- je ne l'ai jamais essayé.)

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16



1 2