boost::function和boost::bind 介绍
一. boost::function介绍
原文:http://www.cnblogs.com/sld666666/archive/2010/12/16/1907591.html
本片文章主要介绍boost::function的用法。 boost::function 就是一个函数的包装器(function wrapper),用来定义函数对象。
1. 介绍
Boost.Function 库包含了一个类族的函数对象的包装。它的概念很像广义上的回调函数。其有着和函数指针相同的特性但是又包含了一个调用的接口。一个函数指针能够在能以地方被调用或者作为一个回调函数。boost.function能够代替函数指针并提供更大的灵活性。
2. 使用
Boost.Function 有两种形式:首选形式和便携式形式, 其语法如下:
| 首选形式 | 便携式形式 |
| boost::function<float(int x, int y)>f | boost::function2<float, int, int>f |
但是便携式形式不是所有的编译器都支持的, 所以这里我只介绍首选形式。
2.1 普通函数
我们可以看下如下的例子:
void do_sum(int *values, int n)
{
int sum();
for (int i = ; i < n; ++i)
{
sum += values[i];
}
cout << sum << endl;
};
int _tmain(int argc, _TCHAR* argv[])
{
boost::function<void(int *values, int n)> sum;
sum = &do_sum;
int a[] = {,,,,};
sum(a, );
return ;
}
sum 可以理解为一个广义的函数对象了,其只用就是保存函数do_sum, 然后再调用之。
2.2 成员函数
在很多系统中, 对于类的成员函数的回调需要做特殊处理的。这个特殊的处理就是“参数绑定”。当然这个超出了我们讨论的范围了。 boost::function对于成员函数的使用可以看下如下代码:
class X{
public:
int foo(int a)
{
cout << a <<endl;
return a;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
boost::function<int(X*, int)>f;
f = &X::foo;
X x;
f(&x, );
return ;
}
我们发现, 对类的成员函数的对象化从语法是没有多大的区别。
3. 一个典型的例子
上面的几个例子没有体现出boost::function的作用来, 这里在写一个例子。比如当程序执行到某一处的时候想绑定某一个函数, 但是不想立即执行, 我们就可以声明一个函数对象,给此对象绑定相应的函数, 做一些其他事情,然后再来执行绑定的函数, 代码如下:
void print(int a)
{
cout << a << endl;
}
typedef boost::function<void (int)> SuccessPrint;
int _tmain(int argc, _TCHAR* argv[])
{
vector<SuccessPrint> printList;
SuccessPrint printOne = boost::bind(print, _1);
printList.push_back(printOne);
SuccessPrint printTwo = boost::bind(print, _1);
printList.push_back(printTwo);
SuccessPrint printThree = boost::bind(print, _1);
printList.push_back(printTwo);
// do something else
for (int i = ; i < printList.size(); ++i)
printList.at(i)(i);
return ;
}
上述代码中首先把声明一个函数对象 typedef boost::function<void (int)> SuccessPrint, 然后把print绑定到斥对象中, 放入vector中, 到最后才来执行这print()函数。
二. boost::bind介绍
最近在几经波折之后,终于对于boost::bind有点理解了。对于习惯了其他语言的人来说,boost::bind是个挺神奇的东西,它可以将你的方法适配成任何其他的方法。其实这得益于c++的模板以及操作符重载,去看boost::bind的实现就会发现它是一个有n多重载的函数,这些重载主要是为了适应函数的参数个数。
其实boost::bind的原理是函数对象,而函数对象就是一个重载了()操作符的对象,这样我们就可以像调用一个方法一样来调用一个类上的这个操作符,比如a(),其实你是在调用a这个对象的()方法,而不是调用一个叫a的方法。
一般来说boost::bind有两种方式的调用,一种是对自由方法,也取非类方法, 一种是对类方法。
对自由方法来说,直接boost::bind(函数名, 参数1,参数2,...)
对类方法来说,直接boost::bind(&类名::方法名,类实例指针,参数1,参数2)
这里需要额外注意的问题是,函数对象也可以像自由方法一样被bind,而boost::function也是一种函数对象。
接下来我们需要注意什么情况下需要用_1, _2这样的参数。
举个例子
void test(int a, int b, int c)
boost::bind(test, 1, _1, _2)得到一个函数对象b,当我们调用b(3,4)时,相当于调用test(1,3,4)
boost::bind(test, _2, 3, _1)得到一个函数对象b,当我们调用b(3,4)时,相当于调用test(4,3,3)
看明白了没有?你实际上可以指定一些常量和一些占位符进去,_x这样的就是占位符,_1表示实际调用时的参数位置,也即b(3,4)时_1代表3,_2代表4
当然你也可以将所有的参数都指定,比如boost::bind(test,1,2,3),那么在调用b()时就相当于调用test(1,2,3)
需要注意的一点是,boost::bind里的参数个数一定要与被bind的函数相同,否则这个函数对象就无法生成了,编译器会抱怨一堆信息,如果你仔细看的话,它是在告诉你,没有这样的函数,你实际的函数是....,这是使用c++很杯具的一点,当遇到模板时,一旦报错,那些信息直接可以令人崩溃。
在asio中,boost::bind被大量使用,原因是异步的情况下,每个函数的调用是独立的,它的所有信息应该包含在它的调用,也即函数对象中。因此asio中有大量的模板,如果在这种情况下你想要使用虚函数或者继承来写框架的话,会是一件很杯具的事情,在碰了很多次壁之后,我发现其实很多情况下我并不需要纯虚函数,我需要的只是一个函数指针,或者函数对象而已。
boost::function和boost::bind 介绍的更多相关文章
- 以boost::function和boost:bind取代虚函数
转自:http://blog.csdn.net/Solstice/archive/2008/10/13/3066268.aspx 这是一篇比较情绪化的blog,中心思想是“继承就像一条贼船,上去就下不 ...
- [置顶] 编程模仿boost::function和boost::bind
boost::function和boost::bind结合使用是非常强大的,他可以将成员函数和非成员函数绑定对一个对象上,实现了类似C#的委托机制.委托在许多时候可以替代C++里面的继承,实现对象解耦 ...
- boost::function和boost:bind取代虚函数
以boost::function和boost:bind取代虚函数 这是一篇比较情绪化的blog,中心思想是"继承就像一条贼船,上去就下不来了",而借助boost::function ...
- boost::function 通过boost::bind调用类成员函数
1. 首先引用boost::function和boost::bind的头文件和库: #include "boost/bind.hpp" #include "boost/f ...
- 关于boost::function与boost::bind函数的使用心得
最近开始写一个线程池,期间想用一个通用的函数模板来使得各个线程执行不同的任务,找到了Boost库中的function函数. Boost::function是一个函数包装器,也即一个函数模板,可以用来代 ...
- boost function bind ref
boost::function to encapsulate function pointers. 1. function #include <boost/function.hpp> #i ...
- [转] boost::function用法详解
http://blog.csdn.net/benny5609/article/details/2324474 要开始使用 Boost.Function, 就要包含头文件 "boost/fun ...
- boost::function用法详解
要开始使用 Boost.Function, 就要包含头文件 "boost/function.hpp", 或者某个带数字的版本,从 "boost/function/func ...
- boost::function的简单实现
前言 boost::function和boost:bind是一对强大的利器.相信用过的童鞋多少有些体会. 虽然平时在用boost::function,但是用的时候心中总会一些不安,因为不知道它是怎么实 ...
随机推荐
- Juicer 轻量级javascript模板引擎
juicer是一个javascript轻量级模板引擎. 使用方法 编译模板并根据数据立即渲染出结果 1 juicer(tpl, data); 仅编译模板暂不渲染,返回一个可重用的编译后的函数 1 va ...
- gulp的安装和使用
安装nodejs -> 全局安装gulp -> 项目安装gulp以及gulp插件 -> 配置gulpfile.js -> 运行任务 1.去nodejs官网安装nodejs 2. ...
- Yii2.0 的安装学习
视频学习地址: 后盾网视频: http://www.houdunren.com/houdunren18_lesson_76?vid=7350 与<Yii框架>不得不说的故事—基础篇 htt ...
- python可视化动态图表: 关于pyecharts的sankey桑基图绘制
最近因工作原因,需要处理一些数据,顺便学习一下动态图表的绘制.本质是使具有源头的流动信息能够准确找到其上下级关系和流向. 数据来源是csv文件 导入成为dataframe之后,列为其车辆的各部件供应商 ...
- 20181206(re,正则表达式,哈希)
1.re&正则表达式 2.hashlib 一:re模块&正则表达式 正则:正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描 ...
- Linux实现内容分发的主备模式的智能DNS
BIND实现智能DNS的原理是通过view的方式,首先判断客户请求的来源,然后返回不同的IP 规划:为za.com域进行智能解析 分2个网段,192.168.1.0/24网段的请求解析到192.168 ...
- 如何固定电脑IP
百度经验里有:http://jingyan.baidu.com/article/2f9b480d579fc041cb6cc297.html 但是就关于如何填写DNS时,就不知道咋办了,特意问了一下IT ...
- mysql查询的语法
单表查询语法 SELECT DISTINCT 字段1,字段2... FROM 表名 WHERE 条件 GROUP BY field HAVING 筛选 ORDER BY field LIMIT 限制条 ...
- Linux的档案权限与目录配置
重点回顾:1.Linux的每个档案中,依据权限分为使用者.群组与其他人三种身份 2.群组最有用的功能之一,就是当你在团队开发资源的时候,且每个账号都可以有多个群组的支持 3.利用"ls -l ...
- MyString的简单实现
MyString.h 文件 #ifndef _STRING_H_ #define _STRING_H_ #include <iostream> using namespace std; c ...