Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Pointeur de méthode?

10 réponses
Avatar
Gégé
Salut,

J'aimerais savoir s'il est possible de cr=E9er un pointer non pas de
fonction mais de m=E9thode ( autre que statique )
Ci-apr=E8s un exemple qui renvoie une erreur de compilation pour "a.f1"

error C2276: '&' : illegal operation on bound member function
expression

Merci
G


class A
{

public :

double f1( double x )
{
return x * x;
}

static double f2( double x )
{
return x * x;
}

A(){}
~A(){}
};

double f3( double x )
{
return x * x;
}

int main( void )
{
A a;
double (*h1)( double ) =3D &a.f1;
double (*h2)( double ) =3D &A::f2;
double (*h3)( double ) =3D &f3;

}

10 réponses

Avatar
Jean-Marc Bourguet
Gégé writes:

Salut,

J'aimerais savoir s'il est possible de créer un pointer non pas de
fonction mais de méthode ( autre que statique )
Ci-après un exemple qui renvoie une erreur de compilation pour "a.f1"

error C2276: '&' : illegal operation on bound member function
expression



Oui, mais un pointeur vers fonction membre n'est pas un pointeur vers
fonction, il faut l'appeler avec un objet. Remplace ton main() par:

int main( void )
{
A a, *p = &a;
double (A::*h1)( double ) = &A::f1;
double (*h2)( double ) = &A::f2;
double (*h3)( double ) = &f3;

(a.*h1)(1.0);
(p->*h1)(1.5);
(*h2)(2.0);
(*h3)(3.0);
}

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Gégé
merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...
Avatar
Bertrand
Gégé wrote:
merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...



C'est moche, mais (à ma connaissance) le seul moyen d'y arriver est le
suivant:

A* a;

double a_f1_callback( double d1, double d2 )
{
// devrait peut-être vérifier la validité de a?
return a->f1( d1, d2 );
}

void quelque_part()
{
A a1;
A a2;

a = &a1;
libfunction( x, a_f1_callback ); // appel avec a1

a = &a2;
libfunction( x, a_f1_callback ); // appel avec a2
}

si cela doit s'exécuter dans un contexte multi-thread, il faut alors
protéger a pendant le temps de l'exécution de libfunction.

je suppose que f1 est en fait une méthode const, donc A const* a devrait
faire l'affaire.

--
Bertrand
Avatar
Gégé
Effectivement c'est une piste !
Mais comme souligné ca va être un peu sale à intégrer dans mon proj et.

Je pense que je vais plutot renverser le pb :
* au lieu que la fonction de la lib se servir de la méthode
* je vais utiliser la méthode pour se servir de la fonction de lib

Je vais perdre en généricité, mais bon ca sera plus clean

Merci encore pour toutes ces réponses
Avatar
pjb
Gégé writes:

merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...



class Class {
public:
virtual double membre(double x,double y);
};


Class* c=new Class;
double x=3.14;

libfunction(x,boost::bind(&Class::membre,c,_1,_2));


--
__Pascal Bourguignon__
Avatar
Michael DOUBEZ
Pascal J. Bourguignon wrote:
Gégé writes:

merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...



class Class {
public:
virtual double membre(double x,double y);
};


Class* c=new Class;
double x=3.14;

libfunction(x,boost::bind(&Class::membre,c,_1,_2));



Je serais surpris que boost::function<void,double,double> se dégrade en
void (*)(double,double)

Même les lambdas de C++0x ne le font pas ce qui est dommage.

--
Michael
Avatar
pjb
Michael DOUBEZ writes:

Pascal J. Bourguignon wrote:
Gégé writes:

merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...


class Class {
public:
virtual double membre(double x,double y);
};
Class* c=new Class;
double x=3.14;
libfunction(x,boost::bind(&Class::membre,c,_1,_2));



Je serais surpris que boost::function<void,double,double> se dégrade
en void (*)(double,double)

Même les lambdas de C++0x ne le font pas ce qui est dommage.



Oops, j'ai tellement l'habitude de travailler avec boost::function que
je n'ai pas remarqué qu'on voulait une simple fonction C...

Il reste une possibilité, pour le faire automatiquement, c'est
d'utiliser une bibliothèque comme ffcall ou llvm pour générer un
tramplin. C'est quelque chose qu'on pourrait ajouter à boost...

boost::trampoline<double(*)(double,double)>(boost::bind(&Class::membre,c,_1,_2))

--
__Pascal Bourguignon__
Avatar
Michael DOUBEZ
Pascal J. Bourguignon wrote:
Michael DOUBEZ writes:

Pascal J. Bourguignon wrote:
Gégé writes:

merci pour cette réponse

En fait j'ai une fonction (d'une librairie) donc le prototype est du
genre :

libfunction( double x, (double *f)( double, double ) );

Je voulais l'utiliser sur une fonction membre, du coup je ne vais pas
pouvoir ...


class Class {
public:
virtual double membre(double x,double y);
};
Class* c=new Class;
double x=3.14;
libfunction(x,boost::bind(&Class::membre,c,_1,_2));


Je serais surpris que boost::function<void,double,double> se dégrade
en void (*)(double,double)

Même les lambdas de C++0x ne le font pas ce qui est dommage.



Oops, j'ai tellement l'habitude de travailler avec boost::function que
je n'ai pas remarqué qu'on voulait une simple fonction C...

Il reste une possibilité, pour le faire automatiquement, c'est
d'utiliser une bibliothèque comme ffcall ou llvm pour générer un
tramplin. C'est quelque chose qu'on pourrait ajouter à boost...

boost::trampoline<double(*)(double,double)>(boost::bind(&Class::membre,c,_1,_2))



C'est une idée mais ce serait limité à gcc et VC++.

L'idéal aurait été que le standard supporte la création de fonctions à
la volée ou que les lambdas puisses se traduire en tant que thunks. Un
volontaire ? :)

--
Michael
Avatar
Gégé
Bon, j'ai peut etre une solution en passant par des struct et des void
*

struct v_params
{
double (*f)( double k, void * p);
void * p;
};

struct v1_params
{
double v;
};

double v1_func( double x, void * p )
{
v1_params v1 = *( v1_params*) p;
return v1.v + x;
}

class A
{

public:

virtual v_params * v() = 0;
A(){}
~A(){}

};

class A1 : public A
{
public:
v_params * v()
{
v1_params * v1 = new v1_params;
v1->v = 2;

v_params * vp = new v_params;
vp->f = &v1_func;
vp->p = v1;

return vp;
}

A1(){}
~A1(){}
};

int main()
{
A * a = new A1();
v_params * v = a->v();
double x = v->f( 55, v->p );

return 0;
}

Qu'en dites-vous?
Avatar
Michael DOUBEZ
Gégé wrote:
Bon, j'ai peut etre une solution en passant par des struct et des void
*

struct v_params
{
double (*f)( double k, void * p);
void * p;
};

struct v1_params
{
double v;
};

double v1_func( double x, void * p )
{
v1_params v1 = *( v1_params*) p;
return v1.v + x;
}

class A
{

public:

virtual v_params * v() = 0;
A(){}
~A(){}

};

class A1 : public A
{
public:
v_params * v()
{
v1_params * v1 = new v1_params;
v1->v = 2;

v_params * vp = new v_params;
vp->f = &v1_func;
vp->p = v1;

return vp;
}

A1(){}
~A1(){}
};

int main()
{
A * a = new A1();
v_params * v = a->v();
double x = v->f( 55, v->p );

return 0;
}

Qu'en dites-vous?



Que ça ne résoudpas le problème tel que je l'ai compris. Le but étant de
passer un void (*)(double,double) en paramètre d'une bibliothèque en vue
d'une utilisation ultérieure; le souhait serait d'utiliser un appel à un
objet et celade façon paramètrablle. A moins d'avoir un moyen de
contraindre les paramètres qu'il lui seront passés, je ne voit pas
comment lui passer une structure.

Quand je fait un programme avec des callbacks en C, j'ajoute toujours un
void* optionnel stocké avec le callback (set/get_context). C'est dommage
qu'il n'y ait pas d'équivalent ici.

--
Michael