C++ 将任何类的任何成员函数作为回调函数传递
我正在开发一个包含一些按钮的OpenGL菜单。我希望能够将一个操作(任何类的成员函数(带有固定签名))与一个按钮相关联,当按下按钮时,该按钮将被执行。我现在可以做,但只有一种类型。我希望能够使用任何类的任何成员函数进行回调 现在我是这样做的: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
#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>