Получить указатель на функцию объекта-объекта
Вот проблема:
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*);
Ответы
Ответ 1
Вы не можете, по крайней мере, это будет не только указатель на функцию.
Функция-член является общей для всех экземпляров этого класса. Все функции-члены имеют неявный (первый) параметр - 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;
}
Подробнее здесь, в Часто задаваемые вопросы по С++
Используя Boost, это может выглядеть так:
#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);
Ответ 2
Вы можете написать какой-то Wrapper, который может использовать как функцию, так и метод как параметр.
Я использовал следующие классы для запуска функций (он использовался в одной моей программе 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)
действительно полезно
Ответ 3
Нет, вы не можете получить указатель на метод класса С++ (если только метод не объявлен статическим). Причина в том, что метод класса всегда имеет указатель this
, указатель на его класс. Но нужно ли вы вызвать метод с помощью указателя, этот указатель не смог бы инкапсулировать этот указатель, а затем тогда не будет присоединен класс, и поэтому это поведение не является законным.
Ответ 4
В то время как не совсем то, что вы запросили, если вы можете использовать С++ 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); };
}
Ответ 5
Я использовал библиотеку Boost. Я включил "boost/bind.hpp" в свой код. Затем метод с именем "fn" можно определить как
auto fn = boost:: bind (ClassName:: methodName, classInstanceName, boost:: placeholders:: _ 1);