使用tr1的bind函数模板
就我个人理解的这个新标准来看,借由这两个模板,我们将能更灵活的使用函数指针,比如函数指针的调用和使用回调机制等。通过使用占位符,我们将可以使用成员函数来进行回调,不得不说,这让我们的编程方式得以更加现代化。
如代码所示:
#include <functional> typedef std::tr1::function<void (int)> Functor;
如上,通过std::tr1::function
我们定义了Functor的函数类型,该类函数的返回值为void ,参数为int类型,
void showNum(int param) { std::cout << "param is : "<<param <<std::endl; } void testSimpleFunctional() { Functor namedFunc = Functor(&showNum); Functor namedFunc2 = bind(&showNum,std::tr1::placeholders::_1); namedFunc(22); namedFunc2(33); }
返回的结果如你所料:
param is : 22 param is : 33
首先,我们定义了一个void int类型的函数showNum,然后将函数以模板HandlerEvent赋值给namedFunc,然后调用namedFunc,而namedFunc2 则使用bind模板,将showNum绑定到namedFunc2上,使用占位符std::tr1::placeholders::_1
来表明其参数,其最后的效果 和直接调用showNum都是一样的。那么,你可能会问,我还不如直接调用showNum来的爽快,是的,在这种情况下,确实如此。
那么,使用std::tr1::function的场景在哪里呢,答案之一是事件回调,答案之二是委托;
事件回调
回调算是老生常谈了,在异步非阻塞的事件驱动的编程模型中,回调机制属于一等公民,像Nodejs这样的平台,回调已经内嵌为基本实现了,这里不展开说明了。为了实现回调,以前,我们经常使用的就是函数指针。现在,让我们使用bind来实现下:
Show Me The Code
class CallBackCls { public: void setCallback(const Functor& callBackFunc){ m_callBackFunc = callBackFunc; } private: Functor m_callBackFunc; public: void run(int param){ //below to do the opetration std::cout << "callcls handle it done and call" << std::endl; //operation done and notify the callee if(m_callBackFunc){ m_callBackFunc(param); } } }; class MainCls { public: MainCls(int x):m_x(x){ m_callBackCls.setCallback(std::tr1::bind(&MainCls::onCallBack,this,x)); } void mainRun(){ m_callBackCls.run(m_x); } private: void onCallBack(int param){ std::cout << "after callback parm callBackFunc in Main is:"<<param <<std::endl; } CallBackCls m_callBackCls; int m_x; };
//在Main函数中测试
MainCls cd = MainCls(555); cd.mainRun();
结果:
callcls handle it done and call:
parm callBackFunc in Main is:555
分析可知:通过bind将MainCls的成员函数onCallBack以及其参数绑定为回调函数,执行run后,CallBackCls的run函数将在执行完自己的任务后回调MainCls的成员函数onCallBack,通过这种方式,可以很好的达到非阻塞的目的。
另外,通过类的继承,虚函数等,我们可以向深挖掘更多高级的用法,这里不展开了。
委托
委托(delegate)在C#里风生水起,而在C++里却是相对沉寂,因为C++没有,只有类似的委托。可参考长文
面向对象的函数指针也被称为闭包(closures) 或委托(delegates), 在类似的语言中已经体现出了它的价值. 在 Delphi(Object Pascal) 中, 他们是 VCL (Borland's Visual Component Library, 宝蓝可视化组件) 的基础. 最近的 C# 让委托的概念更为流行, 这也成为 C# 成功的因素之一. 在许多程序中, 委托可以简化由松耦合对象组成的高级设计模式(观察者模式, 策略模式, 状态模式)的使用. 毫无疑问, 委托在 C++ 中也是非常有用的.
理论上说,委托应该算是回调的一种,即 委托机制的本质就是调用成员函数的函数指针,实现回调。事实上,本文开篇的例子已经算是委托的一种了,但是没有涉及到具体的类,显示有些多余,而一旦使用了类的成员函数,我们就将对象的状态以及类的成员变量都汇集在一起,函数指针的可用性被大大增强了。例子有机会再补充吧。