Andrew
Andrew

Reputation: 24846

c++ store a pointer to a member function of unknown class

I want to store a pointer to an object and a pointer to it's method of known signature. If I know the class then this pointer have type:

int (MyClass::*pt2Member)(float, char, char)

But how can i store the pointer if i don't know the type?

I want to do something like this:

myObject.callThisFuncLater(&otherObject, &otherObject::method)

How can i store a pointer to method method in myObject and call it later ?

Upvotes: 5

Views: 3394

Answers (4)

Daniele Pallastrelli
Daniele Pallastrelli

Reputation: 2552

You can use boost::function (and boost::bind) to store a piece of code to be called later.

class MyClass
{
public:
    void callThisFuncLater( boost::function< int (float, char, char) > callBack );
};
...
myObject.callThisFuncLater( boost::bind( &otherObject::method, &otherObject ) );

Upvotes: 2

Brian Coleman
Brian Coleman

Reputation: 1070

The easiest way to do it if you have access to the TR1 STL library extensions (available on gcc and Visual Studio 2008 and onwards is. std::function and std::bind can be used to wrap an invocation which can be called later. This functionality is also available in boost function and boost bind:

#include <functional>

class MyClass {
public:
  template<typename T> callThisFuncLater(T& otherObject,
                                         int(T::*)(float, char, char) method) {
    return storedInvocation_ = std::bind(otherObject, 
                                  method, 
                                  std::placeholders::_1,   // float
                                  std::placeholders::_2,   // char
                                  std::placeholders::_3);  // char
  }

  int callStoredInvocation(float a, char b, char c) {
    storedInvocation_(a, b, c);
  }

private:
  std::function<int(float, char, char)> storedInvocation_;
};

Upvotes: 5

Nate
Nate

Reputation: 12829

There is no simple way of doing this as originally built into the language or standard library (although, it has recently been added). If you're familiar with Boost, they include a solution for this - Boost.Function.

If for some reason, however, you're unable or unwilling to use Boost, there is a generic way of doing this using templates (which, admittedly, is rather similar to Boost's solution):

class FncPtr
{
public:
    virtual int call(float, char, char) = 0;
};

template <typename T>
class ClassFncPtr : public FncPtr
{
     int (T::*pt2Member)(float, char, char);
     T *inst;
public:
     ClassFncPtr(T* who, int (T::*memfunc)(float,char,char))
         : inst(who), pt2Member(memfunc)
     {
     }
     int call(float a, char b, char c)
     {
         return (inst->*pt2Member)(a,b,c);
     }
};

template <typename T>
FncPtr * makeFuncPointer(T* who, int (T::*memfunc)(float,char,char))
{
    return new ClassFncPtr<T>(who,memfunc);
}

You can also subclass FncPtr to be able to use non-class functions, if you'd like.

Upvotes: 4

Tommy Andersen
Tommy Andersen

Reputation: 7220

Personally I would choose a different design. Simply because member function pointers in C++ are not easy to work with. Personally I would choose to use interfaces and inherit from these and parse along these.

One of the problems with member function pointers is that they are implemented differently on different compilers. If you use the Borland/Embarcardero compilers and want to limit yourself to this, you can use the __closure keyword, however most likely you are not, and therefore you would have to either use some other compiler specific implementation, or use one of the boost helper classes like function.

But if you are in a situation where you find it helpful to use member function pointers in C++, reconsider your design.

Upvotes: 0

Related Questions