Pass any member function of any class as a callback function

I am working on an OpenGL menu that contains several buttons. I want to be able to associate an action (a member function (with a fixed signature) of any class!) With a button that starts when the button is clicked. I can do it right now, but only for one type. I want to be able to use any member function of any class for my callback.

Now I am doing this:

#define BUTTONCALLBACK(Func) bind1st( mem_fun( &ClassICanSupport::Func ), this )

Then I can create a button like this:

Button* b = new Button("Bla", BUTTONCALLBACK(functionIWanttoCall));

The callback function has the following signature:

void callback(Button* source);

When I press the button, I can execute the callback function that I passed.

boost:: bind, . , Object, void *, typeid, . , ( ) .

?

+3
4

, boost::function boost::bind ( std::function std::bind, ++ 0x), -

// in Button class (or whatever signature you need)
Button(const std::string&, boost::function<void(Button*)> callback) // ...
// you can then use callback as a function

// in calling code
Button *b = new Button("..", boost::bind(&Class::func, this));
+3

function<void(Button*)>. , void operator()(Button*). Boost, TR1 ++ 0x. boost::bind .

+1

Well, the easiest way would be with virtual functions if you don't want to retract Boost or don't have access to C ++ 0x.

#include <iostream>

// fwd declare
class Button;

class BtnCallbackBase{
public:
  virtual void operator()(Button*) = 0;
};

template<class C>
class BtnCallback : public BtnCallbackBase{
private:
  typedef void (C::*callback_func)(Button*);

  C* _object;
  callback_func _onclick;

public:
  BtnCallback(C* obj, callback_func func)
    : _object(obj)
    , _onclick(func)
  {}

  virtual void operator()(Button* btn){
    (_object->*_onclick)(btn);
  }
};


class Button{
public:
  Button()
    : _onclick(0)
  {}

  void Click(){
    if(_onclick != 0)
      (*_onclick)(this);
  }

  template<class C>
  void RegisterCallback(C* obj, void (C::*func)(Button*)){
    // cleanup old callback, deleting null pointer is a noop
    delete _onclick;
    _onclick = new BtnCallback<C>(obj,func);
  }

  ~Button(){
    delete _onclick;
  }

private:
  BtnCallbackBase* _onclick;
};

class MyClass{
public:
  void ExampleCallback(Button* btn){
    std::cout << "Callback works!\n";
  }
};

int main(){
  Button btn;
  MyClass test;

  btn.RegisterCallback(&test, &MyClass::ExampleCallback);

  btn.Click();
}

Full example on Ideone.

+1
source

If you want to solve the problem without using the Boost library / without using the new C ++ features, then one of the best options is the General Callback Manager discussed by Danny Kalev / Herb Sutter.

http://www.gotw.ca/gotw/083.htm

0
source

All Articles