传递任何类的任何成员函数作为Callback函数

| 我正在处理包含一些按钮的OpenGL菜单。我希望能够将一个动作(任何类的成员函数(具有固定签名)!)与一个按钮相关联,该按钮在按下按钮时会执行。我现在可以做,但只能用于一种类型。我希望能够使用任何类的任何成员函数进行回调。 现在,我正在这样做:
#define BUTTONCALLBACK(Func) bind1st( mem_fun( &ClassICanSupport::Func ), this )
然后,我可以创建一个像这样的按钮:
Button* b = new Button(\"Bla\", BUTTONCALLBACK(functionIWanttoCall));
回调函数具有以下签名:
void callback(Button* source);
当我按下按钮时,我可以执行我传递的回调函数。 我看过boost :: bind,但是我真的找不到解决问题的方法。此外,我所有的类都是从对象Object派生的,所以我想到了一个void *,我可以通过使用typeid hack将其转换为正确的类,但无法使其正常工作。最后,我总是遇到一个问题,就是我无法完全消除回调函数的类类型(将函数指针保存在我的按钮类中是必需的)而仍然能够调用该函数。 您有解决该问题的想法吗?     
已邀请:
不要使用指针,将
boost::function
boost::bind
一起使用(如果是C ++ 0x,则将
std::function
std::bind
一起使用),例如
// 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));
    
您应该使用“ 8”对象。它们是运行时多态的,可以与支持
void operator()(Button*)
的任何对象一起使用。您可以在Boost,TR1和C ++ 0x中找到一个。
boost::bind
非常适合这些对象。     
好吧,如果您不想使用Boost或无法访问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();
}
有关Ideone的完整示例。     
如果您想在不使用Boost库/不使用新C ++功能的情况下解决问题,那么最好的选择之一是Danny Kalev / Herb Sutter讨论的Generic Callbacks Dispatcher。 http://www.gotw.ca/gotw/083.htm     

要回复问题请先登录注册