0

I'm not sure if this is possible in C++. I know you can pass a pointer to a function or static member function as a parameter. I want a function pointer for a specific object, so that when the function is executed, it is done on the object.

class MyClass
{
   public:
      MyClass(int id){mId = id;}
      void execute(){cout<<mId<<endl;}
   private:
      int mId;
};


MyClass obj1(1);
MyClass obj2(2);

typedef (Executor)();
Executor ex1 = &obj1::execute();
Executor ex2 = &obj2::execute();

So when ex1 is executed, "1" should be printed and if ex2 is execute, "2" is printed. Is this possible?

1
  • 1
    look at {std,boost}::function
    – PlasmaHH
    Commented Oct 22, 2012 at 14:59

3 Answers 3

9

The facility that handles this is the function template bind:

auto ex1 = std::bind(&MyClass::execute, obj1);

You can store a bind in a function object:

std::function<void()> ex1 = std::bind(&MyClass::execute, obj1);

Note that by default bind will store obj by value; you can store a reference with ref:

std::function<void()> ex1 = std::bind(&MyClass::execute, std::ref(obj1));

A related facility is mem_fn, which wraps a member function pointer:

void (MyClass::*ex1)() = &MyClass::execute;  // raw member function pointer
ex1(obj1);

auto ex1 = std::mem_fn(&MyClass::execute);   // mem_fn wrapper
ex1(obj)

However, because mem_fn doesn't bind an instance, you have to supply the instance each time you call it.


In order to avoid writing the class name when binding a member function, you can use a macro:

#define BIND_MEM_FN(o,m) \
    std::bind(&std::remove_reference<decltype(o)>::type::m, (o))

A macro is necessary because you can only form a member function pointer from its type and name, and you cannot pass a name (an unqualified-id) to a function.

5
  • std::mem_fn has some related functionality which may be of interest to the OP, though the invocation of a member function pointer isn't quite as neat as the invocation of a bind, as you have to pass the instance in as an explicit parameter.
    – Rook
    Commented Oct 22, 2012 at 15:10
  • Didn't know there was something like this in C++ STL. I wanted to write my own. Isn't there a way where you can simple say obj::execute, without having to pass the function (&MyClass::execute) and the the object (obj)? So basically a way of automatically detecting that obj (in obj::execute) is not a class and the interpreting it as an object. Commented Oct 22, 2012 at 15:56
  • And this is for C++11, isn't there a way (or maybe a macro) for this in the older version? Commented Oct 22, 2012 at 15:57
  • @goocreations - boost::bind()/boost::function() will work for those without c++11 support. And not there is no "auto-detection"
    – Lou
    Commented Oct 22, 2012 at 16:06
  • @goocreations in older versions of C++ you can use std::bind1st with std::mem_fun and store the result in boost::function; see boost.org/doc/libs/1_51_0/doc/html/function/…
    – ecatmur
    Commented Oct 22, 2012 at 16:16
1

It's possible, but not the way you describe it. You can do it the way proposed by the above comments but more elegant and C++ way would be to use functors. Functor is basically an object which has operator () overloaded. In your case it can be something like this:

class MyClass
{
   public:
       MyClass(int id){mId = id;}
       void operator()(){cout<<mId<<endl;}
   private:
   int mId;
};

MyClass obj1(1);
MyClass obj2(2);

obj1();
obj2();

This way your object actually mimics function behavior. Here you can read more: http://en.wikipedia.org/wiki/Function_object#In_C_and_C.2B.2B

3
  • I don't really want to use functors. In this case you always have to put your implementation in the () operator. And if you do it in a different function, you need a lot of overhead code. Commented Oct 22, 2012 at 15:53
  • In this case you can have a pointer to member as your class data member and set it to an appropriate private method in the constructor. The operator () will just have to call the method pointed by that data member. This way you can benefit from both worlds. And you also have no encapsulation violation. Commented Oct 22, 2012 at 16:04
  • Yip, that was what I meant. I want a solution that is as "clean" as possible. I think I'll go with you idea. thanks. Commented Oct 22, 2012 at 17:20
0

Member function pointers:

typedef void (MyClass::*Executor)();
Executor ex1 = &MyClass::execute;
Executor ex2 = &MyClass::execute;

obj1.*ex1();
obj2.*ex2();

EDIT: Corrected the code as mentioned in the comments.

I made a mistake because I rarely use (member) function pointers indeed. But not because I use std::bind, but because I use polymorphism :)

Actually I don't remember the last time I used a (member) function pointer except in interfacing with OS APIs. Member function pointers are better than non-member function pointers, and std::bind/std::function might be better than member function pointers, but polymorphism is better than all of the above.

1
  • 1
    Maybe I've made a simple mistake, but I'm getting the following error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Seems like you'd be better off with std::bind or std::mem_fn.
    – Rook
    Commented Oct 22, 2012 at 15:08

Not the answer you're looking for? Browse other questions tagged or ask your own question.