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

Passage en paramètres de fonctions membres

4 réponses
Avatar
PurL
Bonjour,

-soit une classe CGestionRessource qui gere une ressource qui génère des
évenements par l'intermédiaire d'appels de fonction callback ; ces fonctions
sont membres privées de CGestionRessource.
-soit d'autres classes utilisatrices de CGestionRessource. Pour qu'une des
fonctions callback de CGestionRessource envoie des données reçues de la
ressource à l'objet utilisateur, je voudrais transmettre à CGestionRessource
une fonction membre de la classe utilisatrice.

d'abord définissons le type d'une fonction membre :
typedef void (__closure *typeFonctionMembre)(char *buffer);

Ensuite la classe qui gere la ressource (tout le code relatif à la gestion
de la ressource a été enlevé pour plus de clarté) :

class CGestionRessource
{
private:
//variable recevant la fonction membre de la classe utilisatrice
typeFonctionMembre m_fct;
public:
CGestionRessource ()
{
}

//construction et definition de m_fct simultanées
CGestionRessource (typeFonctionMembre fct)
{
m_fct = fct;
}

//definition de m_fct
void SetCallBack(typeFonctionMembre fct)
{
m_fct = fct;
}
};

ensuite une classe utilisatrice :

class CUtilisatrice
{
public:
void Fct(char *buffer)
{
//fonction appelée par CGestionRessource
//son prototype correspond bien au type typeFonctionMembre
}

};

ensuite dans le main :

si je fais la définition via la fonction membre SetCallBack de
CGestionRessource :

CUtilisatrice *u = new CUtilisatrice;
CGestionRessource *gr = new CGestionRessource ;
gr->SetCallBack(u->Fct);

ça marche sans probleme :
par contre, si j'utilise le constructeur de CGestionRessource pour faire la
définition :

CUtilisatrice *u = new CUtilisatrice;
CGestionRessource *gr = new CGestionRessource (u->Fct);

J'ai l'erreur suivante :
[C++ Erreur] Unit1.cpp(45): E2235 Une fonction membre doit être appelée ou
son adresse prise

Pouquoi le passage de ce parametre de type fonction membre est accepté quand
il est fait dans une fonction normale et refusé quand il est fait dans le
constructeur ?

Merci,

PurL

4 réponses

Avatar
Olivier Azeau
PurL wrote:
Bonjour,

-soit une classe CGestionRessource qui gere une ressource qui génère des
évenements par l'intermédiaire d'appels de fonction callback ; ces fonctions
sont membres privées de CGestionRessource.
-soit d'autres classes utilisatrices de CGestionRessource. Pour qu'une des
fonctions callback de CGestionRessource envoie des données reçues de la
ressource à l'objet utilisateur, je voudrais transmettre à CGestionRessource
une fonction membre de la classe utilisatrice.


Décrit comme ça, on dirait un pattern 'Command'

d'abord définissons le type d'une fonction membre :
typedef void (__closure *typeFonctionMembre)(char *buffer);


Je ne connais pas __closure
Pourquoi parle-t-on de fonction membre sans référence à une classe ?

Ensuite la classe qui gere la ressource (tout le code relatif à la gestion
de la ressource a été enlevé pour plus de clarté) :

class CGestionRessource
{
private:
//variable recevant la fonction membre de la classe utilisatrice
typeFonctionMembre m_fct;
public:
CGestionRessource ()
{
}

//construction et definition de m_fct simultanées
CGestionRessource (typeFonctionMembre fct)
{
m_fct = fct;
}

//definition de m_fct
void SetCallBack(typeFonctionMembre fct)
{
m_fct = fct;
}
};
ensuite une classe utilisatrice :

class CUtilisatrice
{
public:
void Fct(char *buffer)
{
//fonction appelée par CGestionRessource
//son prototype correspond bien au type typeFonctionMembre
}

};


Ce que je ne comprends pas c'est comment est réalisé l'appel sur m_fct
dans CGestionRessource. Il faut bien avoir une référence à une instance
de CUtilisatrice quelque part non ?

Avatar
Ivan Vecerina
"PurL" wrote in message
news:4215ac73$0$17285$
d'abord définissons le type d'une fonction membre :
typedef void (__closure *typeFonctionMembre)(char *buffer);
__closure n'est pas une fonctionnalité standard du C++ mais, si

je me souviens correctement, une extension spécifique de Borland.
C'est donc hors sujet ici, à demander sur un forum spécifique
à cette plate-forme.

si je fais la définition via la fonction membre SetCallBack de
CGestionRessource :

CUtilisatrice *u = new CUtilisatrice;
CGestionRessource *gr = new CGestionRessource ;
gr->SetCallBack(u->Fct);

ça marche sans probleme :
par contre, si j'utilise le constructeur de CGestionRessource pour faire
la
définition :

CUtilisatrice *u = new CUtilisatrice;
CGestionRessource *gr = new CGestionRessource (u->Fct);

J'ai l'erreur suivante :
[C++ Erreur] Unit1.cpp(45): E2235 Une fonction membre doit être appelée ou
son adresse prise

Pouquoi le passage de ce parametre de type fonction membre est accepté
quand
il est fait dans une fonction normale et refusé quand il est fait dans le
constructeur ?
Aucune idée, fonctionnalité non standard -- mais ne semble pas logique.


En C++ standard, on peut utiliser une librairie comme boost::function
pour faire la même chose (cette lib est candidate pour intégration
dans la librairie standard du C++).



--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form

Avatar
Alexandre
bonjour,

Je ne connais pas __closure


extension de borland. Extrait de la doc C++ Builder :
"Le mot clé __closure est utilisé pour déclarer un type particulier de
pointeur sur une fonction membre. En C++ standard,le seul moyen d'obtenir un
pointeur sur une fonction membre est d'utiliser le nom complet du membre.En
utilisant un closure, vous pouvez obtenir un pointeur sur une fonction
membre d'un objet (c'est-à-dire sur une instance donnée d'une classe).
L'objet peut être quelconque, sans tenir compte de sa hiérarchie d'héritage.
Le pointeur this de l'objet est automatiquement utilisé lors de l'appel de
la fonction membre via le closure. Exemple :
derived derivedObject;
void (__closure *derivedClosure)(int);
derivedClosure = derivedObject.new_func; // Obtient un pointeur sur le
membre 'new_func'.
// Attention, le closure est
associé avec
// un objet particulier :
'derivedObject'.
derivedClosure(3); // Appelle 'new_func' via le closure.

Avatar
Loïc Joly
Alexandre wrote:
bonjour,


Je ne connais pas __closure



extension de borland. Extrait de la doc C++ Builder :
"Le mot clé __closure est utilisé pour déclarer un type particulier de
pointeur sur une fonction membre. En C++ standard,le seul moyen d'obtenir un
pointeur sur une fonction membre est d'utiliser le nom complet du membre.En
utilisant un closure, vous pouvez obtenir un pointeur sur une fonction
membre d'un objet (c'est-à-dire sur une instance donnée d'une classe).
L'objet peut être quelconque, sans tenir compte de sa hiérarchie d'héritage.
Le pointeur this de l'objet est automatiquement utilisé lors de l'appel de
la fonction membre via le closure. Exemple :
derived derivedObject;
void (__closure *derivedClosure)(int);
derivedClosure = derivedObject.new_func; // Obtient un pointeur sur le
membre 'new_func'.
// Attention, le closure est
associé avec
// un objet particulier :
'derivedObject'.
derivedClosure(3); // Appelle 'new_func' via le closure.


A ce que j'ai compris, l'équivalent en C++ standard et avec l'aide de
boost serait :

Derived derivedObject;
boost::function<void(int)> f boost::bind(derivedObject, &Base::new_func);

--
Loïc