Get a pointer to object's member function

坚强是说给别人听的谎言 提交于 2019-11-28 05:49:33

You cannot, at least it won't be only a pointer to a function.

Member function is common for all instances of this class. All member functions have implicit (first) parameter - this. To call a member function for specific instance you need pointer to this member function and this 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;
}

More info here in C++ FAQ

Using Boost this can look like (C++11 provides similar functionality):

#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);

C++11's labdas:

#include <functional>

Some_class sc;
auto f = [&sc]() { sc.some_function(); };
f();
// or
auto f1 = [](Some_class& sc) { sc.some_function(); };
f1(sc);

You may write some kind of Wrapper which is able to use both function or method as parameter.

I used following classes for launching functions (it was used in one my SDL program):

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);
}

And this extension for "methods":

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);
}

And then use it as:

CallbackFunction *callback;
callback = new CallbackFunction( myFunction);
callback = new CallbackMethod<A>( instanceOfA, instanceOfA::myMethod);
callback = new CallbackMethod<B>( instanceOfB, instanceOfB::myMethod);
...
callback( keysym);

I found macro as this:

CALLBACK(object,method) new CallbackMethod<typeof(*object)>( object, &method)

really useful

No, you can't get a pointer to a C++ class method (unless the method is declared static). The reason is that a class method always has the pointer this, a pointer to the class instance. But were you to call the method through a pointer, that pointer could not encapsulate the this pointer, and then then there would be no instance attached, and therefore this behavior is not legal.

While not exactly what you requested, if you can use C++11 the following might nevertheless suit your needs (untested):

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); };
}

I used the Boost library. I included "boost/bind.hpp" in my code. Then a method named "fn" can be defined as

auto fn = boost::bind(ClassName::methodName, classInstanceName, boost::placeholders::_1);

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!