Des pointeurs sur fonction pour le dessert ? [C++] - Programmation
Marsh Posté le 16-06-2001 à 22:29:34
On ne peut pas (pour les fonctions membres non statiques).
[edit]--Message édité par Verdoux--[/edit]
Marsh Posté le 16-06-2001 à 22:35:54
Je pense quand même qu'il y a un moyen.
Il faut passer par des objets fonction.
Il faut accessoirement que la fonction que tu utilises prenne un paramètre du type de la classe.
ex:
#include <functional>
using namespace std;
class MaClasse
{
...
public:
...
void fonction()
{
//code
}
...
};
void fonctionext(MaClasse & inutile)
{
//code
}
//maintenant tu peut écrire
mem_fun_ref(MaClasse::fonction);
/*qui est une unary_function qui prend en paramètre une instance de classe.
ex
MaClasse c;
c.fonction();
est équivalent à
MaClasse c;
mem_fun_ref(MaClasse::fonction)(c);
Mais tu peux transformer aussi transformer un pointeur sur fonction en une unary_function:
ptr_fun(fonctionext);
est du même type que
mem_fun_ref(MaClasse::fonction);
et je pense que sans trop magouiller, tu dervais t'en sortir.
[edit]--Message édité par janoscoder--[/edit]
Marsh Posté le 16-06-2001 à 22:48:00
Oui les mem_fun<> de la STL permettent ce genre de manip par contre t'auras pas un pointeur mais un objet fonction.
[edit]--Message édité par Verdoux--[/edit]
Marsh Posté le 16-06-2001 à 23:02:21
ce qui n'est en soit pas si grave car on peut transformer un pointeur sur fonction en un objet fonction, et un objet fonction peut se faire évaluer comme une fonction de la manière suivante (ça laisse deux façons de faire).
class Base
{
virtual operator()...
};
void fonctionnormale(Base & rienàfoutre)
{
}
void deBaseàfonctionnormale(Base & cettfoisjelutilise)
{
cettefoisjelutilise();
}
et &deBaseàfonctionnormale et &fonctionnormales sont donc deux * sur fonction de même type.
Bien évidemment, comme operator() n'est pas statique, il faut au moins passer un param..
Dans le cas où c'est statique, y'a pas d'embrouille, il suffit de faire
Base::foncstatique
Marsh Posté le 16-06-2001 à 23:04:41
Oui mais si il voulait un pointeur sur fonction membre pour par exemple alimenter un callback de l'api Win32, ça marchera pas.
Marsh Posté le 16-06-2001 à 23:09:41
tu peux bidouiller avec les macros et les fonctions statiques.
mettons que tu veuilles appeler ta fonction global MyGlobalFunction() et une fonction membre de MyClass MyFunction() avec le même pointeur.
tu définis ta globale comme
void MyGlobalFunction(MyClass* mc);
et ta classe comme
class MyClass
{
void MyFunction();
public:
static void StaticMyFunction(MyClass* mc) { if (mc) mc->MyFunction(); }
};
Tu peux ensuite créer un pointeur de fonction :
void (*myPointer)(MyClass* mc);
pour appeler ta globale :
myPointer = MyGlobalFunction;
myPointer(NULL);
pour appeler la méthode d'une instance myInstance de MyClass :
myPointer = MyClass::StaticMyFunction;
myPointer(myInstance);
et vala
pourquoi je parlais de macro ? si tu as pas mal de fonction à définir comme ça dans ta classe, tu peux utiliser une macro qui définit et la fonction et sa méthode d'appel statique.
#define MyVoidFunction(class, name) void name(); static void Static##name() {class* c) { if (c) c->name(); }
et MyClass devient
class MyClass
{
MyVoidFunction(MyClass, MyFunction)
}
phew. du bidouillage, mais j'adore les macros
Marsh Posté le 16-06-2001 à 23:44:26
Merci à tous, je vais regarder toutes vos réponses à tete reposée. Mais apparemment, d'après ce que j'ai pu lire (en travers), vous me confirmez tous qu'il n'est pas possible de faire un pointeur de fonction générique qui accepterait de pointer sur des fonctions membres (ou de class) et à la fois sur des fonction normales (par opposition aux premières), si bein sur leurs paramètres et type de retour sont identiques pour les deux ?
De mon coté j'ai essayé d'utiliser un (void*) et je ne comprend pas pourqui cela ne pourrait pas marcher avec un pointeur de ce type (même si je suis bien obligé de le constater.)
Un autre truc que je trouve bizzar : dites moi ce que vous pensez de la remarque de mon compilateur (gcc) lorsque je tente un cast (P) (définition de mon pointeur : void (*P)() ) sur le nom de ma fonction membre (void MenuNavi::suivant() ) avant de faire pointer mon pointeur dessus :
CMenuNavi.cc:128: converting from `void (MenuNavi::*) ()' to `void (*) ()'
make: *** [CMenuNavi.o] Erreur 1
Apparemment la conversion marche mais la compilation s'interrompt !!
Encore merci pour vos réponses
Marsh Posté le 17-06-2001 à 01:12:08
j'imagine que la fonction MenuNavi n'est pas statique, donc elle prend un paramètre, mais qui n'est pas dans les parenthèses : c'est l'instance de classe courante.
En effet, on peut voir une fonction c++ comme
Maclasse c;
c.Fonction();
qui pourrait être convertie en internet comme:
Maclasse c;
__MaclasseFonction(&c);
Mais si tu regardes ce que j'ai dit dans mes posts, je te dis que c'est possible, mais il faut accepter de prendre au moins un param, qui est une instance de classe, mais que tu pourras négliger le paramètre dans le cas de la fonction globale.
Sinon il reste un moyen crade, si tu n'acceptes pas de paramètre, c'est de faire un instance globale de classe:
MaClasse
{
void fonction(){....}
};
MaClasse c;
void fonction()
{
....
}
void fonctionavecclasse()
{
c.fonction();
}
et voilà
Marsh Posté le 16-06-2001 à 22:05:35
Je voudrais savoir si vous auriez une idée : je dois créer un pointeur sur fonction qui puisse appeler à la fois une simple fonction (telle qu'elle sera décrite dans un fichier d'en-tête) et une méthode de classe (fonction membre). Je ne sais pas si c'est possible ni comment faire.
Merci d'avance pour vos réponses.
PS: je tiens à préciser que bien entendu, toutes les fonctions pointées par ce poinrteur sont du même type, à savoir : elles retournent void et ne prennent pas de paramètres en entrée.