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

PBM: pointeur sur fonction, membres d'une classe

2 réponses
Avatar
david
voici mon code :


/* ==== le fichier [VPUnit.h] =========================== */

#ifndef VPUnitH
#define VPUnitH


class MaClasse
{
public:

MaClasse(void);
~MaClasse();

void (MaClasse::* OnMove)(long); // pointeur sur une fonction,
membre de MaClasse

bool DoSomethingLikeThis(void);


protected:




private:
void _MoveLikeThis(long);
void _MoveLikeThat(long);


};
#endif
/* ====================================================== */









/* ==== le fichier [VPUnit.cpp] ========================= */

MaClasse::MaClasse(void) //construction
{
Move=&MaClasse::MoveLikeThis; // affectation du pointeur sur fonction
}
/**********************************************************/

MaClasse::~MaClasse() //destruction
{
}
/**********************************************************/

void MaClasse::MoveLikeThis(long v)
{
}
/**********************************************************/

void MaClasse::MoveLikeThat(long v)
{
}
/**********************************************************/





bool MaClasse::DoSomethingLikeThis(void)
{
(*Move)(1); // <---- erreur : "illegal use of a member pointer"
return true;
}
/* ====================================================== */



mon probleme : l'erreur du compilateur à propos du

(*Move)(1); // <---- erreur : "illegal use of a member pointer"



Ma problematique :

j'ai un jeu de fonctions qui ont la meme fonctionnalité, mais dont le
fonctionnement interne est différent.
J'utilise l'une ou l'autre en fonction d'un contexte global. Le choix
est guidé par la necessité d'utiliser la solution la moins gourmande en
ressources pour effectuer un travail donné.

je connais 2 façons de faire :

- celle ci (utilisation d'un pointeur qui pointera sur l'une ou
l'autre des fonction selon le contexte)

- creer une fonction générique du style :

/**********************************************************/

bool ItIsUsefullToDoLikeThis;

void MaClasse::Move(long v)
{
if(ItIsUsefulToDoLikeThis)
{
MoveLikeThis(v);
}
else
{
MoveLikeThat(v);
}
}
/**********************************************************/

et ça, je suis sur que l'ont peut faire mieux, ou alors j'abandonne le
C++ et je deviens moine tibetain.

2 réponses

Avatar
Benoit Rousseau
david wrote:
voici mon code :


/* ==== le fichier [VPUnit.h] =========================== */

#ifndef VPUnitH
#define VPUnitH


class MaClasse
{
public:

MaClasse(void);
~MaClasse();

void (MaClasse::* OnMove)(long); // pointeur sur une fonction,
membre de MaClasse

bool DoSomethingLikeThis(void);


protected:




private:
void _MoveLikeThis(long);
void _MoveLikeThat(long);


};
#endif
/* ====================================================== */



/* ==== le fichier [VPUnit.cpp] ========================= */

MaClasse::MaClasse(void) //construction
{
Move=&MaClasse::MoveLikeThis; // affectation du pointeur sur fonction
}
/**********************************************************/

bool MaClasse::DoSomethingLikeThis(void)
{
(*Move)(1); // <---- erreur : "illegal use of a member pointer"
return true;
}
/* ====================================================== */



mon probleme : l'erreur du compilateur à propos du

(*Move)(1); // <---- erreur : "illegal use of a member pointer"


En fait, la fonction a besoin d'un pointeur-this pour être invoquée...
Et ca devient vite compliqué si tu veux utiliser le callback (un
pointeur sur fonction) :
Il faut créer une fonction statique qui englobe ta fonction et l'appelle
avec le bon pointeur...
class A {
public:
static call_back_this( A* this_object, long arg ) {
A->move_like_this( arg );
}
static call_back_that( A* this_object, long arg ) {
A->move_like_that( arg );
}
void move_like_this(long);
void move_like_that(long);
};

Et oui, c'est chiant :-)

Heureusement, il existe un principe assez simple et plus joli: les functors

class Functor {
public:
virtual void go( long arg ) = 0; //Eventuellement passer un this aussi
};

class MoveLikeThis : public Functor {
public:
void go( long arg ) {...};
};

class MoveLikeThat...

class A {
public:
A( Functor* ft) : ft(ft) {...}
Move( long arg ) {
ft->go( arg );
}
protected:
Functor* ft;
};

A a( new MoveLikeThis );
a.go( 1 );

Les deux méthodes ont leurs inconvéniants...



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

Avatar
Loïc Joly
david wrote:

Quand tu postes du code, surtout un peu gros, merci de le compiler chez
toi, afin d'éviter à ceux qui veulent t'aider de devoir corriger
quelques fautes de recopie assez bêtes (les fonctions avec des noms
différents...).

class MaClasse
{
void (MaClasse::* OnMove)(long); // pointeur sur une fonction,
membre de MaClasse
};
bool MaClasse::DoSomethingLikeThis(void)
{
(*Move)(1); // <---- erreur : "illegal use of a member pointer"


(this->*OnMove)(1);


return true;
}

Ma problematique :

j'ai un jeu de fonctions qui ont la meme fonctionnalité, mais dont le
fonctionnement interne est différent.
J'utilise l'une ou l'autre en fonction d'un contexte global. Le choix
est guidé par la necessité d'utiliser la solution la moins gourmande en
ressources pour effectuer un travail donné.

je connais 2 façons de faire :

- celle ci (utilisation d'un pointeur qui pointera sur l'une ou
l'autre des fonction selon le contexte)

- creer une fonction générique du style :

/**********************************************************/

bool ItIsUsefullToDoLikeThis;

void MaClasse::Move(long v)
{
if(ItIsUsefulToDoLikeThis)
{
MoveLikeThis(v);
}
else
{
MoveLikeThat(v);
}
}
/**********************************************************/

et ça, je suis sur que l'ont peut faire mieux, ou alors j'abandonne le
C++ et je deviens moine tibetain.


Si le choix entre les deux méthodes est figé à la création d'une instance :

class MaClass
{
public:
void Move();
private:
virtual void doMove() =0;
};

class MaClassLikeThis : MaClass
{
private:
virtual void doMove() {/*Move like this*/}
};

class MaClassLikeThat : MaClass
{
private:
virtual void doMove() {/*Move like that*/}
};

Si une instance peut avoir un mode, puis l'autre, au cours de sa vie :

class MovingStrategy
{
public:
void Move();
private:
virtual void doMove() =0;
};

class MovingStrategyLikeThis : MovingStrategy
{
private:
virtual void doMove() {/*Move like this*/}
};

class MovingStrategyLikeThat : MovingStrategy
{
private:
virtual void doMove() {/*Move like that*/}
};

class MaClass
{
MovingStrategy *myStrategy;
void setMovingStrategy(bool likeThisOrLikeThat)
{
delete myStrategy;
if (likeThisOrLikeThat)
{
myStategy = new MovingStrategyLikeThis;
}
else
{
myStategy = new MovingStrategyLikeThat;
}
}
void Move() {myStrategy->Move();}
}

--
Loïc