使用tr1的bind函数模板

最近把公司的VS2008统一升级为SP1了,虽然还是有些跟不上时代,毕竟C++17标准都出了,但是,对于成熟的商业软件开发而言,追求更新的C++标准肯定不是正道。升级SP1的VS2008可以支持TR1的C++标准了,算是跟上了部分C++11的脚步。本文将说说TR1中新functional头文件中function和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++ 中也是非常有用的.

理论上说,委托应该算是回调的一种,即 委托机制的本质就是调用成员函数的函数指针,实现回调。事实上,本文开篇的例子已经算是委托的一种了,但是没有涉及到具体的类,显示有些多余,而一旦使用了类的成员函数,我们就将对象的状态以及类的成员变量都汇集在一起,函数指针的可用性被大大增强了。例子有机会再补充吧。

posted @ 2018-11-20 22:26  Lckfa  阅读(376)  评论(0编辑  收藏  举报