Voici le problème:
1) J'ai une classe comme ça:
class some_class
{
public:
some_type some_value;
int some_function(double *a, double *b, int c, int d, void *e);
};
2) À l'intérieur some_function
, J'utilise some_values
de some_class
objet pour obtenir un résultat.
3) Donc, j'ai un objet concret et je veux obtenir un pointeur sur cet objet some_function
.
C'est possible? Je ne peux pas utiliser some_fcn_ptr
car le résultat de cette fonction dépend du béton some_value
d'un objet.
Comment puis-je obtenir un pointeur sur some_function
d'un objet? Merci.
typedef int (Some_class::*some_fcn_ptr)(double*, double*, int, int, void*);
Vous ne pouvez pas, au moins ce ne sera pas seulement un pointeur vers une fonction.
La fonction membre est commune à toutes les instances de cette classe. Toutes les fonctions membres ont un paramètre implicite (premier) - this
. Pour appeler une fonction membre pour une instance spécifique, vous devez pointer vers cette fonction membre et cette instance.
class Some_class
{
public:
void some_function() {}
};
int main()
{
typedef void (Some_class::*Some_fnc_ptr)();
Some_fnc_ptr fnc_ptr = &Some_class::some_function;
Some_class sc;
(sc.*fnc_ptr)();
return 0;
}
Plus d'informations ici dans FAQ C++
En utilisant Boost , cela peut ressembler (C++ 11 fournit des fonctionnalités similaires):
#include <boost/bind.hpp>
#include <boost/function.hpp>
boost::function<void(Some_class*)> fnc_ptr = boost::bind(&Some_class::some_function, _1);
Some_class sc;
fnc_ptr(&sc);
Labdas de C++ 11:
#include <functional>
Some_class sc;
auto f = [&sc]() { sc.some_function(); };
f();
// or
auto f1 = [](Some_class& sc) { sc.some_function(); };
f1(sc);
Vous pouvez écrire une sorte de Wrapper capable d'utiliser à la fois la fonction ou la méthode comme paramètre.
J'ai utilisé les classes suivantes pour lancer des fonctions (il a été utilisé dans un de mes programmes SDL):
class CallbackFunction {
public:
// Constructor, copy constructor and destructor
virtual int execute( SDL_keysym* keysym) const;
virtual int operator()( SDL_keysym* keysym) const;
protected:
int( *callback)( SDL_keysym*));
}
int CallbackFunction::execute( SDL_keysym* keysym) const{
return callback(keysym);
}
int CallbackFunction::operator()( SDL_keysym* keysym) const{
return callback( keysym);
}
Et cette extension pour "méthodes":
template<class T>
class CallbackMethod : public CallbackFunction {
public:
// Constructor, copy constructor and destructor
CallbackMethod( T *object, int(T::*callback)( SDL_keysym* keysym));
int execute( SDL_keysym* keysym) const;
int operator()(SDL_keysym* keysym) const;
protected:
T *object;
int(T::*method)( SDL_keysym* keysym);
};
// Object initialization (constructor)
template<class T>
CallbackMethod<T>::CallbackMethod( T *object, int(T::*callback)( SDL_keysym* keysym)):
CallbackFunction( NULL),object(object),method(callback){
}
// Responsible for executing
template<class T>
int CallbackMethod<T>::execute( SDL_keysym* keysym) const {
return (object->*method)(keysym);
}
template<class T>
int CallbackMethod<T>::operator()( keysym) const {
return (object->*method)( keysym);
}
Et puis utilisez-le comme:
CallbackFunction *callback;
callback = new CallbackFunction( myFunction);
callback = new CallbackMethod<A>( instanceOfA, instanceOfA::myMethod);
callback = new CallbackMethod<B>( instanceOfB, instanceOfB::myMethod);
...
callback( keysym);
J'ai trouvé la macro comme ceci:
CALLBACK(object,method) new CallbackMethod<typeof(*object)>( object, &method)
vraiment utile
Non, vous ne pouvez pas obtenir de pointeur sur une méthode de classe C++ (sauf si la méthode est déclarée statique). La raison en est qu'une méthode de classe a toujours le pointeur this
, un pointeur sur l'instance de classe. Mais si vous appeliez la méthode via un pointeur, ce pointeur ne pourrait pas encapsuler le pointeur this
, puis il n'y aurait aucune instance attachée, et donc ce comportement n'est pas légal.
Bien que ce ne soit pas exactement ce que vous avez demandé, si vous pouvez utiliser C++ 11, les éléments suivants pourraient néanmoins répondre à vos besoins (non testés):
std::function<int(double*, double*, int, int, void*)>
some_function_of(Some_class& obj)
{
return [&](double* a, double* b, int c, int d, void* e){
return obj.some_func(a, b, c, d, e); };
}
J'ai utilisé la bibliothèque Boost . J'ai inclus "boost/bind.hpp" dans mon code. Ensuite, une méthode nommée "fn" peut être définie comme
auto fn = boost :: bind (ClassName :: methodName, classInstanceName, boost :: placeholders :: _ 1);