使用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++ 中也是非常有用的.
理论上说,委托应该算是回调的一种,即 委托机制的本质就是调用成员函数的函数指针,实现回调。事实上,本文开篇的例子已经算是委托的一种了,但是没有涉及到具体的类,显示有些多余,而一旦使用了类的成员函数,我们就将对象的状态以及类的成员变量都汇集在一起,函数指针的可用性被大大增强了。例子有机会再补充吧。
使用tr1的bind函数模板的更多相关文章
- C++ TR1 Function Bind
在C++ 11出现以前,C++的事件一般是通过回调形试来实现,如 void (*func)(int,int,int),其实际上是一种函数指针,在C中调用时是直接写函数名在参数列表中,而在C++中,大部 ...
- 关于boost::function与boost::bind函数的使用心得
最近开始写一个线程池,期间想用一个通用的函数模板来使得各个线程执行不同的任务,找到了Boost库中的function函数. Boost::function是一个函数包装器,也即一个函数模板,可以用来代 ...
- 读书笔记 effective c++ Item 45 使用成员函数模板来接受“所有兼容类型”
智能指针的行为像是指针,但是没有提供加的功能.例如,Item 13中解释了如何使用标准auto_ptr和tr1::shared_ptr指针在正确的时间自动删除堆上的资源.STL容器中的迭代器基本上都是 ...
- c++ stl bind函数介绍
/* stl::bind 使用 */ #include <iostream> #include <string> #include <functional> /* ...
- c++函数模板作为类的成员函数,编译报错LNK2019的解决方法
为了使某个类的成员函数能对不同的参数进行相同的处理,需要用到函数模板,即template<typename T> void Function(). 编译时报错LNK2019 解决方法: 1 ...
- C++STL - 函数模板
模板主要是为了泛型编程,做到与类型无关 模板有函数模板和类模板,本文主要整理的是函数模板 1.函数模板定义 template<typename 类型形参1,typename 类型形参2,...& ...
- 使用getopt_long来解析参数的小函数模板
getopt_long原型 #define no_argument 0 #define required_argument 1 #define optional_argument 2 struct o ...
- (十一)socket、connect、bind函数详解
一.socket函数 1.头文件: #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> 2.函数原型: ...
- C++函数重载和函数模板
1.函数重载 这是小菜鸟写的一个例子. 函数重载应该注意以下几点: 1.1重载函数有类似的功能: 1.2只能以参数的类型(形参个数和类型)来重载函数, int max(int a,int b);flo ...
随机推荐
- 永久更改hostname主机名
vim /etc/sysconfig/network NETWORKING=yesHOSTNAME=keepalived-nginx1GATEWAY=192.168.33.2 vim /etc/hos ...
- C#设计模式之控制反转即依赖注入-Spring.NET
主流的依赖注入方案:微软企业库中的Unity.Spring.NET.StructureMap.Ninject.Castle Windsor等等. 本章用简单的案例讲解 Spring.NET IOC-控 ...
- Python学习札记(十三) Function3 函数参数二
参考:函数参数 Note A.关键字参数: 1.关键字参数:**kw 可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple.而关键字参数允许你传入0个或任意个含参数名的 ...
- java代码实现JVM栈溢出,堆溢出
参考博客:http://www.cnblogs.com/tv151579/p/3647238.html 背景知识: 栈存放什么:栈存储运行时声明的变量——对象引用(或基础类型, primitive)内 ...
- redis——redis主从复制
和MySQL主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况.为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,Redi ...
- JavaScript之右下角广告
网站中,我们都遇到想这样的悬浮广告,我们先给图片设置右下角悬浮属性,关闭按钮键也就是节点的删除: window.onload = function(){ var TipBox = document.g ...
- React 16.3.0 发布,构建用户界面的 JavaScript 库
React 16.3.0 已发布,React 是 Facebook 推出的一个为数据提供渲染为 HTML 视图,用来构建用户界面的开源 JavaScript 库. React 视图通常采用包含以自定义 ...
- 转:在Eclipse的Debug页签中设置虚拟机参数
http://blog.csdn.net/decorator2015/article/details/50914479 在Eclipse的Debug页签中设置虚拟机参数 步骤 1,Run->De ...
- CUDA JPEG编码
基于英伟达的jpegNPP工程,分离实现独立的JPEG压缩. 由于原工程是直接把解码时的jpeg图片的信息直接作为编码时的信息,所以在做独立的JPEG编码时,需要自己来填充各种信息. 1.JPEG编码 ...
- Project facet Java 1.8 is not supported by target runtime Apache Tomcat v7.0.
找到项目下的“.settings”