最近把公司的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函数模板的更多相关文章

  1. C++ TR1 Function Bind

    在C++ 11出现以前,C++的事件一般是通过回调形试来实现,如 void (*func)(int,int,int),其实际上是一种函数指针,在C中调用时是直接写函数名在参数列表中,而在C++中,大部 ...

  2. 关于boost::function与boost::bind函数的使用心得

    最近开始写一个线程池,期间想用一个通用的函数模板来使得各个线程执行不同的任务,找到了Boost库中的function函数. Boost::function是一个函数包装器,也即一个函数模板,可以用来代 ...

  3. 读书笔记 effective c++ Item 45 使用成员函数模板来接受“所有兼容类型”

    智能指针的行为像是指针,但是没有提供加的功能.例如,Item 13中解释了如何使用标准auto_ptr和tr1::shared_ptr指针在正确的时间自动删除堆上的资源.STL容器中的迭代器基本上都是 ...

  4. c++ stl bind函数介绍

    /* stl::bind 使用 */ #include <iostream> #include <string> #include <functional> /* ...

  5. c++函数模板作为类的成员函数,编译报错LNK2019的解决方法

    为了使某个类的成员函数能对不同的参数进行相同的处理,需要用到函数模板,即template<typename T> void Function(). 编译时报错LNK2019 解决方法: 1 ...

  6. C++STL - 函数模板

    模板主要是为了泛型编程,做到与类型无关 模板有函数模板和类模板,本文主要整理的是函数模板 1.函数模板定义 template<typename 类型形参1,typename 类型形参2,...& ...

  7. 使用getopt_long来解析参数的小函数模板

    getopt_long原型 #define no_argument 0 #define required_argument 1 #define optional_argument 2 struct o ...

  8. (十一)socket、connect、bind函数详解

    一.socket函数 1.头文件: #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> 2.函数原型: ...

  9. C++函数重载和函数模板

    1.函数重载 这是小菜鸟写的一个例子. 函数重载应该注意以下几点: 1.1重载函数有类似的功能: 1.2只能以参数的类型(形参个数和类型)来重载函数, int max(int a,int b);flo ...

随机推荐

  1. [CF1051F]The Shortest Statement

    题目大意:给定一张$n$个点$m$条有权边的无向联通图,$q$次询问两点间的最短路 $n\le100000$,$m\le100000$,$1\le100000$,$m$-$n\le20$. 首先看到$ ...

  2. nginx配置Strict Transport Security

    一个网站接受一个HTTP的请求,然后跳转到HTTPS,用户可能在开始跳转前,通过没有加密的方式和服务器对话,比如,用户输入http://zt.test.com或者直接zt.test.com.这样存在中 ...

  3. mySQL 多表查询语句

    多表查询最少有2张以上的表一起查询 交叉连接查询(很少用)查询出来的数据是错误的 内连接 [inner] join on 隐式省略inner join on select  from 表A,表B wh ...

  4. validateJarFile jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class

    项目环境 Maven.Tomcat7.0.27.jdk1.8.0_111 报这个错误的原因是项目中依赖 javax.servlet-api 包和Tomcat本身的包冲突了,Tomcat本身也有这个包 ...

  5. SSM到Spring Boot-从零开发校园商铺平台

    第1章 开发准备 本章包含课程介绍,同时讲解开发网站所需要准备的事情,并且带领大家从零开始搭建一个Maven Web. 1-1 课程导学 1-2 开发准备 第2章 项目设计和框架搭建 本章主要先带领大 ...

  6. 爬虫框架Scrapy之案例一

    阳光热线问政平台 http://wz.sun0769.com/index.php/question/questionType?type=4 爬取投诉帖子的编号.帖子的url.帖子的标题,和帖子里的内容 ...

  7. 解题报告:poj1061 青蛙的约会 - 扩展欧几里得算法

    青蛙的约会 writer:pprp Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 119716 Accepted: 25238 ...

  8. "ImportError: cannot import name OVSLegacyKernelSwitch"

    My VirtualMachine OS is Ubuntu14.04, Linux. Recently I want to install the mininet in my OS, and I u ...

  9. UVa 11768 格点判定(扩展欧几里得求线段整点)

    https://vjudge.net/problem/UVA-11768 题意: 给定两个点A(x1,y1)和B(x2,y2),均为0.1的整数倍.统计选段AB穿过多少个整点. 思路: 做了这道题之后 ...

  10. ubuntu install git vim Plug manage

    在UBUNTU采用163或是阿里云来更新源,最新的更新源地址可以在网上查阅, 阿里源 deb http://mirrors.aliyun.com/ubuntu/ bionic main restric ...