boost--function
1、简介
function是一个模板类,它就像一个包装了函数指针或函数对象的容器(只有一个元素)。可以把它想象成一个泛化的函数指针,而且他非常适合代替函数指针,存储用于回调的函数。如下定义了一个能够容纳void(int)类型的function对象:
function<void(int)> funo;
使用function需要包含头文件"boost/function.hpp",C++11已经支持function。
一些成员函数:
target():返回对象内部的可调用物Functor的指针,对象为空则返回NULL
contains():检测是否持有一个Functor。
clear():将对象清空,与"= 0"效果相同。
empty():测试对象是否为空,也可以在一个bool上下文中直接测试它是否为空。
operator==、operator!=:与一个函数或函数对象进行比较。
operator():调用内部的可调用物,它也会将参数传给可调用物。
2、简单使用
int FuncName(int a, int b)
{
return a + b;
} int main()
{
function<int(int, int)> funo;
funo = FuncName;
if (funo)
{
cout << funo(, ) << endl;
} return ;
}
除了普通函数,function对象中也可以存储Lambda表达式、函数对象(包括bind表达式的结果)、类的成员函数。我们完全可以使用function其来代替函数指针。
3、用于回调
①、存储普通函数
以下为在CTestClass类中使用function对象m_fFun来保存回调函数和调用回调函数的示例,CTestClass的成员函数SetCallBack()被定义成了模板函数,这样更方便:
void call_back_func(int i)
{
cout << i << endl;
} class CTestClass
{
public:
CTestClass(int i) :m_iNum(i) {}
public:
template<typename CallBack>
void SetCallBack(CallBack f)
{
m_fFun = f;
}
void run()
{
if(m_fFun)
m_fFun(m_iNum);
}
private:
function<void(int)> m_fFun;
int m_iNum;
}; int main()
{
CTestClass dc();
dc.SetCallBack(call_back_func);
dc.run(); return ;
}
②、存储Lambda表达式
class Bar
{
public:
std::function<void()> onClick;
}; class Foo
{
public:
Foo()
{
b = new Bar;
//存储Lambda,捕获this指针,使lambda内可调用本类的成员
b->onClick = [this] {
func();
};
}
void func()
{
cout << "func" << endl;
}
private:
Bar* b;
}; int main()
{
//存储Lambda,捕获变量num
int num = ;
std::function<void()> f = [num] {
cout << "num:" << num << endl;
};
f(); getchar();
return ;
}
③、存储函数对象
使用function来存储函数对象是function的重要功能之一,因为相比于使用普通函数回调,使用函数对象回调可以保存数据和实现复杂的操作。以下为在CTestClass类中使用function对象m_fFun来保存回调函数对象和调用回调函数对象的示例
#include "boost/bind.hpp"
class CFunObj
{
public:
CFunObj(int i) :x(i) {}
public:
void operator()(int i)
{
cout << i * x++ << endl;
}
private:
int x;
}; class CTestClass
{
public:
CTestClass(int i) :m_iNum(i) {}
public:
template<typename T>
void SetCallBack(T f)
{
m_fFun = f;
}
void run()
{
if (m_fFun)
m_fFun(m_iNum);
}
private:
function<void(int)> m_fFun;
int m_iNum;
}; int main()
{
CTestClass dc();
CFunObj cfo();
dc.SetCallBack(ref(cfo));
dc.run();
dc.run(); return ;
}
function使用拷贝语义来保存函数或函数对象,当函数或函数对象很复杂或者禁止拷贝的时候可以使用ref()以解决拷贝的问题。从以上示例代码可以看到,在使用SetCallBack设置回调的时候就是使用ref()来传递的引用包装器,SetCallBack是模板函数,所以T类型在函数调用的时候就是ref()引用包装类型。
④、存储类的成员函数
以下我们定义了一个函数工厂类,回调函数都在这个工厂类中定义,我们可以配合bind来保存类中的回调函数,然后通过fiunction对象再调用类中的回调函数:
#include "boost/bind.hpp"
class CCall_back_factory
{
public:
void call_back_fun_1(int i)
{
cout << i * << endl;
}
void call_bcak_fun_2(int i, int j)
{
cout << i * j * << endl;
}
}; class CTestClass
{
public:
CTestClass(int i) :m_iNum(i) {}
public:
template<typename CallBack>
void SetCallBack(CallBack f)
{
m_fFun = f;
}
void run()
{
if(m_fFun)
m_fFun(m_iNum);
}
private:
function<void(int)> m_fFun;
int m_iNum;
}; int main()
{
CTestClass dc();
CCall_back_factory cbf; dc.SetCallBack(bind(&CCall_back_factory::call_back_fun_1, cbf, _1));
dc.run(); int j = ;
dc.SetCallBack(bind(&CCall_back_factory::call_bcak_fun_2, cbf, _1, j));
dc.run(); return ;
}
通过以上示例代码可以看到,function用于回调再配合bind解决了类的成员函数不能作为回调函数的问题,而且使用更加灵活。 C++中A类对象里调用B类对象的成员函数一般使用以下三种方法:
①、使用虚函数:在A类中保存B类对象的基类指针m_ptr,在B类中重写基类的虚函数,通过B类的基类指针m_ptr来调用B类的虚函数。
②、使用function + bind:在A类中保存B类对象的成员函数的function(通过bind),通过function来调用B类的成员函数。
③、使用function + lambda:在A类中保存B类对象的成员函数的function(通过捕获this指针的lambda),通过function来调用B类的成员函数。
4、给线程函数传入多个参数
我们知道,线程函数只有一个void*参数,利用bind和function可以间接实现给线程函数传入多个参数:
#include <Windows.h>
#include "boost/bind.hpp" void RealFun(char* p, int& n)
{
cout << p << n << endl;
n = ;
} DWORD WINAPI ThreadFunc(void* param)
{
function<void()> func = *((function<void()>*)param);
func(); return ;
} int main()
{
char* p = "value is :";
int i = ; function<void()> func = boost::bind(&RealFun, p, ref(i));
HANDLE hThread = CreateThread(NULL, , ThreadFunc, &func, , );
WaitForSingleObject(hThread, INFINITE); assert(i == ); return ;
}
boost--function的更多相关文章
- boost::function的用法
本片文章主要介绍boost::function的用法. boost::function 就是一个函数的包装器(function wrapper),用来定义函数对象. 1. 介绍 Boost.Func ...
- boost::bind 和 boost::function 基本用法
这是一篇介绍bind和function用法的文章,起因是近来读陈硕的文章,提到用bind和function替代继承,于是就熟悉了下bind和function的用法,都是一些网上都有的知识,记录一下,期 ...
- 以boost::function和boost:bind取代虚函数
转自:http://blog.csdn.net/Solstice/archive/2008/10/13/3066268.aspx 这是一篇比较情绪化的blog,中心思想是“继承就像一条贼船,上去就下不 ...
- boost::function实践——来自《Beyond the C++ Standard Library ( An Introduction to Boost )》
代码段1: #include <boost/function.hpp> #include <iostream> float mul_ints(int x, int y) { r ...
- 关于boost::function与boost::bind函数的使用心得
最近开始写一个线程池,期间想用一个通用的函数模板来使得各个线程执行不同的任务,找到了Boost库中的function函数. Boost::function是一个函数包装器,也即一个函数模板,可以用来代 ...
- [转] boost::function用法详解
http://blog.csdn.net/benny5609/article/details/2324474 要开始使用 Boost.Function, 就要包含头文件 "boost/fun ...
- #include <boost/function.hpp>
为atoi取别名fun,fun实质上是函数指针 #include <iostream> #include <boost/function.hpp> void main() { ...
- [置顶] 编程模仿boost::function和boost::bind
boost::function和boost::bind结合使用是非常强大的,他可以将成员函数和非成员函数绑定对一个对象上,实现了类似C#的委托机制.委托在许多时候可以替代C++里面的继承,实现对象解耦 ...
- boost function对象
本文根据boost的教程整理. 主要介绍boost function对象的用法. boost function boost function是什么 boost function是一组类和模板组合,用于 ...
- boost::function 介绍
本片文章主要介绍boost::function的用法. boost::function 就是一个函数的包装器(function wrapper),用来定义函数对象. 1. 介绍 Boost.Func ...
随机推荐
- 写了一个兼容IE9的图片放大器(基于vue)
photoloupe 图片放大器 第一次写vue插件,本人比较喜欢用简单易懂的写法,不喜勿喷. 本插件支持IE9及以上版本,已经过验证. 本插件可根据需要设置放大倍数,最小支持1倍,支持小数 下载地址 ...
- mybatis批量更新update-设置多个字段值 报错 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near
mybatis批量更新update-设置多个字段值 2016年08月01日 12:49:26 姚一号 阅读数:29539 标签: mysql mybatis批量更新批量更新allowMultiQuer ...
- tableViewCell上的定时器拖动阻塞
if (_timer == nil) { _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@sele ...
- BadgeView 圆形数字提醒 购物车常用
实际上BadgeView这个类就是继承TextView的.很多TextView中设置字体的方法都适用于BadgeView. 1. setTargetView(View) --> 设置哪个控件显示 ...
- java String 中替换"\"为"\\"
表示路径的字符串 c:\work\test\afd.out, 要形成 c:\\work\\test\\afd.out 用 String str = strBsf.replaceAll(" ...
- jQuery的鼠标悬停时放大图片的效果
这是一个基于jQuery的效果,当鼠标在小图片上悬停时,会弹出一个大图,该大图会跟随鼠标的移动而移动.这个效果最初源于小敏同志的一个想法,刚开始做的时候只能实现弹出的图片是固定的,不能随鼠标移动,最后 ...
- Jenkins构建.net项目
一.环境搭建 1.安装所需软件 Jenkins\JDK\GIT\VS\IIS\nginx(可选) 1.1 安装iis服务: 控制面板—>程序和功能—>启用或关闭windows功能,勾选所有 ...
- 基于kafka-net实现的可以长链接的消息生产者
今天有点时间,我就来说两句.最近接触的Kafka相关的东西要多一些,其实以前也接触过,但是在项目使用中的经验不是很多.最近公司的项目里面使用了Kafka消息中间件,由于以前的人员编写的客户端的类不是很 ...
- Oracle性能优化5-索引的不足
索引的不足 1.索引开销 a.访问开销 反问集中导致热块的竞争(对最新数据的查询) 回表性能取决聚合因子 索引的访问开销,返回几条数据快,但是返回大量的数据很慢 全表扫描与全扫描 ...
- js iterable类型
遍历Array可以采用下标循环,遍历Map和Set就无法使用下标.为了统一集合类型,ES6标准引入了新的iterable类型,Array.Map和Set都属于iterable类型. 具有iterabl ...