C++ 将任何类的任何成员函数作为回调函数传递

C++ 将任何类的任何成员函数作为回调函数传递,c++,callback,function-pointers,member-function-pointers,C++,Callback,Function Pointers,Member Function Pointers,我正在开发一个包含一些按钮的OpenGL菜单。我希望能够将一个操作(任何类的成员函数(带有固定签名))与一个按钮相关联,当按下按钮时,该按钮将被执行。我现在可以做,但只有一种类型。我希望能够使用任何类的任何成员函数进行回调 现在我是这样做的: #define BUTTONCALLBACK(Func) bind1st( mem_fun( &ClassICanSupport::Func ), this ) Button* b = new Button("Bla", BUTTONCALLBA

我正在开发一个包含一些按钮的OpenGL菜单。我希望能够将一个操作(任何类的成员函数(带有固定签名))与一个按钮相关联,当按下按钮时,该按钮将被执行。我现在可以做,但只有一种类型。我希望能够使用任何类的任何成员函数进行回调

现在我是这样做的:

#define BUTTONCALLBACK(Func) bind1st( mem_fun( &ClassICanSupport::Func ), this )
Button* b = new Button("Bla", BUTTONCALLBACK(functionIWanttoCall));
然后,我可以创建如下按钮:

#define BUTTONCALLBACK(Func) bind1st( mem_fun( &ClassICanSupport::Func ), this )
Button* b = new Button("Bla", BUTTONCALLBACK(functionIWanttoCall));
回调函数具有以下签名:

void callback(Button* source);
当我按下按钮时,我可以执行我传递的回调函数

我看了一下boost::bind,但实际上找不到解决问题的方法。此外,我所有的类都是从一个类对象派生的,所以我考虑了一个void,我可以用一些typeid技巧将它转换成正确的类,但我无法让它工作。最后,我总是遇到这样的问题:我无法完全消除回调函数的类类型(这对于在button类中保存函数指针是必要的),并且仍然能够调用该函数


你知道如何解决这个问题吗?

不要使用指针,将
boost::function
boost::bind
一起使用(或者
std::function
std::bind
如果是C++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));
//在Button类中(或任何您需要的签名)
按钮(const std::string&,boost::函数回调)/。。。
//然后可以将回调函数用作函数
//在调用代码中
按钮*b=新按钮(“…”,boost::bind(&Class::func,this));

您应该使用
函数
对象。它们是运行时多态的,可以与支持
void操作符()(按钮*)
的任何对象一起使用。您可以在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();
}
#包括
//fwd申报
类按钮;
类BtnCallbackBase{
公众:
虚空操作符()(按钮*)=0;
};
模板
BtnCallback类:公共BtnCallbackBase{
私人:
typedef void(C::*回调函数)(按钮*);
C*_对象;
回调函数onclick;
公众:
BtnCallback(C*obj,回调函数)
:_对象(obj)
,_onclick(func)
{}
虚拟无效运算符()(按钮*btn){
(_object->*_onclick)(btn);
}
};
类按钮{
公众:
按钮()
:_onclick(0)
{}
无效单击(){
如果(_onclick!=0)
(*_onclick)(本);
}
模板
作废注册表回调(C*obj,作废(C::*func)(按钮*){
//清除旧回调,删除空指针是一个noop
删除_onclick;
_onclick=新的BtnCallback(obj,func);
}
~Button(){
删除_onclick;
}
私人:
BtnCallbackBase*_onclick;
};
类MyClass{
公众:
无效示例回调(按钮*btn){

STD::CUT< P>如果不使用Booost库(不使用新的C++特性),那么您需要一个解决方案,那么最好的选择是<强>通用回调调度程序< /强>由<强> Danny Kalev /Habor萨特讨论。<强> < /P>