Получить указатель на функцию-член объекта
вот в чем проблема:
1) у меня есть такой класс:
class some_class
{
public:
some_type some_value;
int some_function(double *a, double *b, int c, int d, void *e);
};
2) внутри some_function
, Я использую some_values
С some_class
объект для получения результата.
3) Итак, у меня есть конкретный объект, и я хочу получить указатель на этот объект some_function
.
возможно ли это? Я не могу использовать some_fcn_ptr
потому что результат этой функции зависит от конкретного some_value
объекта.
как я могу получить указатель на some_function
объекта? Спасибо.
typedef int (Some_class::*some_fcn_ptr)(double*, double*, int, int, void*);
5 ответов
вы не можете, по крайней мере, это будет не только указатель на функцию.
функция-член является общим для всех экземпляров этого класса. Все функции-члены имеют неявный (первый) параметр - this
. Чтобы вызвать функцию-член для конкретного экземпляра вам нужен указатель на функцию-член и этот экземпляр.
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;
}
подробнее здесь C++ FAQ
используя Boost это может выглядеть так (C++11 обеспечивает подобное функциональность):
#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 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);
вы можете написать какую-то оболочку, которая может использовать как функцию, так и метод в качестве параметра.
я использовал следующие классы для запуска функций (он использовался в одной моей программе 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);
}
и это расширение для "методов":
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);
}
и затем использовать его как:
CallbackFunction *callback;
callback = new CallbackFunction( myFunction);
callback = new CallbackMethod<A>( instanceOfA, instanceOfA::myMethod);
callback = new CallbackMethod<B>( instanceOfB, instanceOfB::myMethod);
...
callback( keysym);
Я нашел макрос следующим образом:
CALLBACK(object,method) new CallbackMethod<typeof(*object)>( object, &method)
очень полезным
нет, вы не можете получить указатель на метод класса C++ (если метод не объявлен статическим). Причина в том, что метод класса всегда имеет указатель this
указатель на экземпляр класса. Но если вы вызовете метод через указатель, этот указатель не сможет инкапсулировать this
указатель, а затем тогда не будет прикреплен экземпляр, и поэтому это поведение не является законным.
хотя это не совсем то, что вы просили, если вы можете использовать C++11, тем не менее, может удовлетворить ваши потребности (непроверенные):
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); };
}
Я использовал Boost библиотека. Я включил " boost / bind.ГЭС " в моем коде. Тогда метод с именем " fn " может быть определен как
auto fn = boost:: bind(ClassName:: methodName, classInstanceName, boost:: placeholders:: _1);