如何将boost function转换为指针boostbind 转函数指针

用户名:muzizongheng
文章数:197
访问量:21919
注册日期:
阅读量:1297
阅读量:3317
阅读量:580938
阅读量:464756
51CTO推荐博文
了这篇文章
类别:┆阅读(0)┆评论(0)& & & & 这里稍微解释下何谓指针类型的向下转换和向上转换。向下转换是指派生类指针转换为基类指针类型,向上转换是指基类指针类型转换为派生类类型。C++一般使用dynamic_cast转换符实现向上转换。智能指针可以毫无问题的进行向下类型转换,却不能使用dynamic_cast进行向上类型转换。例如:
#include &boost/shared_ptr.hpp&
class Base
virtual ~Base(){};
protected:
class DeriveClass : public Base
DeriveClass():Base(){};
virtual ~DeriveClass(){};
protected:
int main(int argc, _TCHAR* argv[])
boost::shared_ptr&Base& ptrBase = boost::shared_ptr&DeriveClass&(new DeriveClass()); // 这样转换成功
boost::shared_ptr&DeriveClass& ptrDerive = dynamic_cast&boost::shared_ptr&DeriveClass& &(ptrBase); // 这样出现编译错误
那么怎么实现智能指针的向上转换呢?今天发现boost库有一个dynamic_pointer_cast的模板函数,可以实现智能指针的向上转换。如上例的可以这样写:
boost::shared_ptr&DeriveClass& ptrDerive = boost::dynamic_pointer_cast&DeriveClass&(ptrBase);
另外在osg库中的智能指针向上转换也使用类似的dynamic_pointer_cast的模板函数。
【转自:http://blog.csdn.net/clever101/article/details/6950050】
本文已收录于以下专栏:
相关文章推荐
作者:朱金灿来源:http://blog.csdn.net/clever101         这里稍微解释下何谓指针类型的向下转换和向上转换。向下转换是指派生类指针转换为基类指针类型,向上转换是指基...
#include &boost/shared_ptr.hpp&class Base{public:Base(){};virtual ~Base(){};protected:private:};clas...
static_pointer_cast() 、 const_pointer_cast() 、dynamic_pointer_cast()
扩展:标准的转型操作符
static_cast...
接着下来,需要演示一下怎么样在多个对象里共享一个对象,而不管每个对象的生命周期,就可以及时地把使用的对象在合适地方删除。下面的例子里先定义两个类,然后每个类都引用共享的对象,接着使用完成后,就会在析构...
智能指针的原理,其实就是利用C++的一个特性,当对象创建时,一定会调用构造函数;当对象离开作用域时,会自动调用析构函数。由于这两个函数的调用都是由编译器来生成的,不用怕不调用的危险,达到安全删除的目的...
【Boost介绍】
Boost是个组织(http://www.boost.org/),提供可移植的,源码开放的C++程序库。部分Boost库已经被包含到了C++标准化委员会的TR1中。
目前可以下载到...
什么是智能指针呢,它是行为类似于指针的类对象,但这种对象还有其他功能。我们为什么要封装智能指针类对象呢?这是因为C++中的动态内存需要用户自己来维护,动态开辟的空间,在出函数作用域或者程序正常退出前必...
共享指针 (shared_ptr) 是现在的 Boost 库中提供的,并且应该是将来 C++1x 的标准库中提供的一个模板类。在此之前,ISO/IEC
中的“自动指针...
学习过C++的开发人员,都知道在C++里数组指针与一般的指针是有区别的。比如使用数组形式分配的内存,就需要使用数组的形式删除。但初学开发的开发人员,往往会忘记这点,如下面所示:
char*  p...
他的最新文章
讲师:王哲涵
讲师:韦玮
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)下次自动登录
现在的位置:
Boost – Function 分析
本文假设了解 boost::function 相关用法
首先需要包含的头文件为 boost/function.hpp
里面内容比较简单
if BOOST_FUNCTION_MAX_ARGS &= 0
include &boost/function/function0.hpp&
if BOOST_FUNCTION_MAX_ARGS &= 1
include &boost/function/function1.hpp&
if BOOST_FUNCTION_MAX_ARGS &= 2
include &boost/function/function2.hpp&
if BOOST_FUNCTION_MAX_ARGS &= 3
include &boost/function/function3.hpp&
默认的 BOOST_FUNCTION_MAX_ARGS 为 10,说明最大支持为10个参数
那么,可以知道引入了function0 ~ function10 共11个文件
第N个文件都是定义了支持 N 个参数的 function 类
我们以参数 BOOST_FUNCTION_MAX_ARGS = 4 来看看定义
boost/function/function4.hpp 头文件里只有这样几行
#define BOOST_FUNCTION_NUM_ARGS 4
#include &boost/function/detail/maybe_include.hpp&
#undef BOOST_FUNCTION_NUM_ARGS
boost/function/detail/maybe_include.hpp 里面其实就定义了 BOOST_FUNCTION_N
#if BOOST_FUNCTION_NUM_ARGS == 0
ifndef BOOST_FUNCTION_0
define BOOST_FUNCTION_0
include &boost/function/function_template.hpp&
#elif BOOST_FUNCTION_NUM_ARGS == 1
ifndef BOOST_FUNCTION_1
define BOOST_FUNCTION_1
include &boost/function/function_template.hpp&
#elif BOOST_FUNCTION_NUM_ARGS == 2
ifndef BOOST_FUNCTION_2
define BOOST_FUNCTION_2
include &boost/function/function_template.hpp&
boost/function/function_template.hpp 首先看两个宏定义
#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
#define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
BOOST_FUNCTION_NUM_ARGS 就是当前文件支持的参数个数,当前是4 BOOST_FUNCTION_TEMPLATE_PARMS 是宏自身扩展,展开时可能如下:
#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
// typename T0 , typename T1 , typename T2 , typename T3
// 同样 BOOST_FUNCTION_TEMPLATE_ARGS 展开如下
// T0 , T1 , T2 , T3
可以看到,我们用宏展开后的结果,function里都是一些构造函数和赋值函数,所以应该主要工作都在基类中
template&typename R , typename T0 , typename T1 , typename T2 , typename T3&
class function&R ( T0 , T1 , T2 , T3)& : public function4&R , T0 , T1 , T2 , T3& {
typedef function4&R , T0 , T1 , T2 , T3& base_
typedef function self_
struct clear_type {};
function() : base_type() {}
// 模板的 sfinae 原则,避免整数被选入
template&typename Functor&
function(Functor f,
typename enable_if_c&
(boost::type_traits::ice_not&
(is_integral&Functor&::value)&::value),
int&::type = 0) : base_type(f) {}
template&typename Functor,typename Allocator&
function(Functor f, Allocator a,
typename enable_if_c&(
boost::type_traits::ice_not&(
is_integral&Functor&::value)&::value),int&::type = 0) :
base_type(f,a) {}
function(clear_type*) : base_type() {}
function(const self_type& f) : base_type(static_cast&const base_type&&(f)) {}
function(const base_type& f) : base_type(static_cast&const base_type&&(f)) {}
self_type& operator=(const self_type& f) {
self_type(f).swap(*this);
template&typename Functor&
typename enable_if_c&(boost::type_traits::ice_not&
(is_integral&Functor&::value)&::value),
self_type&&::type
operator=(Functor f) {
self_type(f).swap(*this);
self_type& operator=(clear_type*) {
this-&clear();
self_type& operator=(const base_type& f) {
self_type(f).swap(*this);
所看看它基类的内容
template&typename R , typename T0 , typename T1 , typename T2 , typename T3&
class function4 : public function_base
typedef R result_
typedef boost::detail::function::basic_vtable4&R , T0 , T1 , T2 , T3& vtable_
struct clear_type {};
template&typename Functor&
function4(Functor f,
typename enable_if_c&(boost::type_traits::ice_not&
(is_integral&Functor&::value)&::value), int&::type = 0) {
this-&assign_to(f);
// 主要赋值在这个函数
template&typename Functor&
void assign_to(Functor f) {
using detail::function::vtable_
// 以下两行是得到 Functor 的类型
// 这个是由 tag 做萃取器的
typedef typename detail::function::get_function_tag&Functor&::
typedef detail::function::get_invoker4&tag& get_
typedef typename handler_type::invoker_type invoker_
typedef typename get_invoker::template apply&Functor, R ,T0 , T1 , T2 , T3& handler_
// vtable_type 负责实际 Functor 映射到内部 function_buffer 的管理
// 这里之所以用静态的是因为同一种类型的 assign_to都是一样的策略
// 不同 Functor 自然生成不同的 assign_to,那么 stored_vtable 也自然不同了
static vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to(f, functor)) {
std::size_t value = reinterpret_cast&std::size_t&(&stored_vtable.base);
if (boost::has_trivial_copy_constructor&Functor&::value &&
boost::has_trivial_destructor&Functor&::value &&
detail::function::function_allows_small_object_optimization&Functor&::value) {
value |= (std::size_t)0x01;
vtable = reinterpret_cast&detail::function::vtable_base *&(value);
vtable = 0;
上面看有两个成员变量是比较重要的,一个是 vtable, 一个是 function
他们都在基类 function_base 中被描述
class function_base {
detail::function::vtable_base*
// 真正存储的指针
mutable detail::function::function_
union function_buffer {
mutable void* obj_
// 对象指针类型
mutable void (*func_ptr)(); // 函数指针类型
// 指针本身的类型, 比如是const约束? volite约束?
struct type_t {
const detail::sp_typeinfo*
bool const_
bool volatile_
// 成员函数指针的结构
struct bound_memfunc_ptr_t {
void (X::*memfunc_ptr)(int);
void* obj_
} bound_memfunc_
// 对象引用类型
struct obj_ref_t {
mutable void* obj_
bool is_const_
bool is_volatile_
// 小函数对象的优化
// 如果是小函数对象,那么直接构造在这个 union 上
// 这个是干嘛用的现在还不清楚
struct vtable_base {
void (*manager)(const function_buffer& in_buffer,
function_buffer& out_buffer,
functor_manager_operation_type op);
萃取器的 tag 代码如下
struct function_ptr_tag {};
struct function_obj_tag {};
struct member_ptr_tag {};
struct function_obj_ref_tag {};
template&typename F&
class get_function_tag {
// 这是个依次迭代的关系
// 巧妙啊,这样解决了定义 type 为不同类型的问题
// 其实是一个 if-else 的编译期选择绑定
typedef typename mpl::if_c&(is_pointer&F&::value),
function_ptr_tag,
function_obj_tag&::type ptr_or_obj_
typedef typename mpl::if_c&(is_member_pointer&F&::value),
member_ptr_tag,
ptr_or_obj_tag&::type ptr_or_obj_or_mem_
typedef typename mpl::if_c&(is_reference_wrapper&F&::value),
function_obj_ref_tag,
ptr_or_obj_or_mem_tag&::type or_ref_
typedef or_ref_
// vtable_type 大概代码如下
typedef boost::detail::function::basic_vtable0&R& vtable_
template&typename R &
struct basic_vtable4
template&typename F&
bool assign_to(F f, function_buffer& functor) {
typedef typename get_function_tag&F&::
return assign_to(f, functor, tag());
// 以下重载了几种 tag
// 普通指针对象
template&typename FunctionPtr&
bool assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) {
this-&clear(functor);
// 普通函数指针都是转换成 (void (*)())(f) 指针
functor.func_ptr = (void (*)())(f);
// 仿函数对象
template&typename FunctionObj&
bool assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) {
if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
// 小对象优化
assign_functor(f, functor,
mpl::bool_&(function_allows_small_object_optimization&FunctionObj&::value)&());
// 具体的小对象优化
template&typename FunctionObj&
void assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) {
functor.obj_ptr = new FunctionObj(f);
template&typename FunctionObj&
void assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) {
new ((void*)&functor.data) FunctionObj(f);
最后调用一目了然了
inline function4&R , T0 , T1 , T2 , T3&::operator()( T0 a0 , T1 a1 , T2 a2 , T3 a3) const {
if (this-&empty())
boost::throw_exception(bad_function_call());
return get_vtable()-&invoker
(this-&functor , a0 , a1 , a2 , a3);
&&&&推荐文章:
【上篇】【下篇】boost线程使用带参数的类成员函数方法
假设类VZController有成员函数如下:
void downloadData(std::string filename); &
需要将下载数据的部分放到一个单独的线程去执行下载过程,但文件的保存需要通过主线程指定,如何实现?
可以借助boost::function和boost::bind来生成一个包装函数对象,然后对函数对象进行参数绑定实现,具体代码如下:
#include &boost/bind.hpp& &
#include &boost/function.hpp& &
#include &boost/thread/thread.hpp& &
& std::string localFileName = &D:\\temp\\dl.dat&; &
& boost::function&void (std::string)& memberFunctionWrapper(boost::bind(&VZController::downloadData, this, _1)); &
& boost::thread downloadThread = new boost::thread(boost::bind(memberFunctionWrapper, localFileName)); &
&如果要传递多个参数的话,也很方便,把函数对象的定义改一下就可以。
&Boost线程库学习笔记&(/younes/archive//1752745.html)里面也介绍了一个给线程函数传递参数的方法,不过比这个方法麻烦一些,我也没有试验过是不是可以用在类对象的成员函数上。最近在写代码过程中需要使用boost::function,在此之前并没有接触过boost::function,这里主要记录下对boost::function的学习和理解。
boost::function是一个函数对象的“容器”,概念上像是C/C++中函数指针类型的泛化,是一种“智能函数指针”。它以对象的形式封装了原始的函数指针或函数对象,能够容纳任意符合函数签名的可调用对象。因此,它可以被用于回调机制,暂时保管函数或函数对象,在之后需要的时机在调用,使回调机制拥有更多的弹性。
既然boost::function经常被用于回调机制,我们就先看看什么是回调函数吧.
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
其实,之前博主在实际项目中就使用过回调函数带来的方便。记得当时的需求时这样的:有一个链表用来记录一组数据,最大能记录400条记录,这400条数据能根据用户的选择(支持编号(int),距离(float)进行排序)进行排序显示。当时为了使排序算法更为通用,就使用了回调函数。
我们先来看看c/c++中函数指针在普通函数和类成员函数的使用吧!
#include &iostream&
class CEventQ
typedef bool (*CommonFuncPoint)(void);
//普通函数指针
typedef bool (CEventQuery::*ClassFuncPoint)(int); //类成员函数指针
bool CommonFunc(void)
//这是个回调函数,当特定的事件或条件发生
//的时候,会被调用。
cout && &CallBackFunc Common Function Call!& &&
//这里会有特定事件或条件发生时需要处理的事
class CEventQuery
CEventQuery(CommonFuncPoint eventFunc)
:m_Event(eventFunc)
~CEventQuery()
void Query(void)
//这里会检测某个事件或条件的发生
//比方说这里查询到了事件发生或条件的改变,那么就回调处理函数
m_Event();
bool DoSomething(int iValue)
cout && &Class Function DoSomething Parament : & && iValue &&
CommonFuncPoint m_E
int main(void)
CEventQuery tEventQuery(CommonFunc);
tEventQuery.Query();
ClassFuncPoint ClassFunc1 = &CEventQuery::DoS
(tEventQuery.*ClassFunc1)(10);
tEventQuery.DoSomething(20);
}运行结果如下所示:
CallBackFunc Common Function Call!
Class Function DoSomething Parament : 10
Class Function DoSomething Parament : 20
不足的地方是,这种方式的调用只适用于函数指针,不适用于非函数指针(比如函数对象),这就是局限性。
与之前使用函数指针不同,function就像是一个函数的容器,也可以把function想象成一个泛化的函数指针,只要符合它声明中的函数类型,任何普通函数,成员函数,函数对象都可以存储在function对象中,然后在任何需要的时候被调用。
boost::function能够代替函数指针,并且能能接受函数或函数对象,增加了程序的灵活性。当然,带来好处的同时,也必然有弊端。boost::function相比函数指针来说体积稍大一点,速度上稍慢一点。不过相比于boost::function带来的灵活性相比速度和体积就显得举足轻重了。
查看Boost官方文档,Boost.Function 有两种形式:首选形式和便携式形式, 其语法如下:
便携式语法
&float (int x, int y)&
&float, int, int&
这两种形式等价,大家可以选择一种自己喜欢使用的形式即可(有一些较老的编译器不支持便携式)。
作为示范,我们的例子展示了:普通函数、类成员函数、函数对象的使用。当然function可以配合bind使用,存储bind表达式的结果,使bind可以被多次调用。目前没用到,下次再补充。
#include &iostream&
#include &boost/function.hpp&
template&typename Func&
class CFuncDemo
CFuncDemo(int iValue)
:m_iValue(iValue)
template&typename CallBackFunc&
void acceptFunc(CallBackFunc Func)
m_Func = F
void CommonResult()
m_Func(m_iValue);
template&typename T&
void ClassMemberResult(T &t)
m_Func(t, m_iValue);
void FuncObjResult()
m_Func(m_iValue);
//普通函数
void CommonFunc(int iValue)
cout && &CallBack Common Function& &&
cout && &2 * iValue = & && 2 * iValue &&
//这个类有个成员函数完成类似的功能
class CMultiple
void ClassFunc(int iValue)
cout && &CallBack Class Member Function& &&
cout && &3 * iValue = & && 3 * iValue &&
//这里有个函数对象同样也完成对应的功能
class CFuncObj
void operator()(int iValue)
cout && &CallBack Function Object& &&
cout && &4 * iValue = & && 4 * iValue &&
int main(void)
//作为示范的测试用例,这里我们展示了:普通函数、类成员函数、函数对象的使用
//普通函数
CFuncDemo&boost::function&void(int)&& tFuncCommon(10);
tFuncCommon.acceptFunc(CommonFunc);
monResult();
//类成员函数
CMultiple tM
CFuncDemo&boost::function&void(CMultiple &, int)&& tFuncClassMember(10);
tFuncClassMember.acceptFunc(&CMultiple::ClassFunc);
tFuncClassMember.ClassMemberResult(tMember);
//函数对象
CFuncObj tO
CFuncDemo&boost::function&void(int)&& tFuncObj(10);
//tFuncObj.acceptFunc(tObj);
//function使用拷贝语义保存参数,使用ref它允许以引用的方式传递参数
tFuncObj.acceptFunc(boost::ref(tObj));
tFuncObj.FuncObjResult();
}下面是测试结果:
CallBack Common Function
2 * iValue = 20
CallBack Class Member Function
3 * iValue = 30
CallBack Function Object
4 * iValue = 40关于boost::function的基本用法就讲解完毕。
本文已收录于以下专栏:
相关文章推荐
要开始使用 Boost.Function, 就要包含头文件 &boost/function.hpp&, 或者某个带数字的版本,从
&boost/function/function0.hpp& 到
要开始使用 Boost.Function, 就要包含头文件 &boost/function.hpp&, 或者某个带数字的版本,从&boost/function/function0.hpp& 到 &bo...
Tuples 位于名字空间 tuples, 后者又位于名字空间 boost.
使用这个库要包含头文件 &boost/tuple/tuple.hpp&。关系操作符的定义在头文件&boost/...
Boost.Bind 为函数和函数对象提供了一致的语法,对于值语义和指针语义也一样。我们将从一些简单的例子开始,处理一些简单绑定的用法,然后再转移到通过嵌套绑定进行函数组合。弄明白如何使用 bind ...
boost::program_options 用法详解boostprogram_options 用法详解
示例二简介
program options是一系列pai...
函数组合,Part II
在SGI STL中的另一个常用的函数组合是 compose1 ,在 pose 中是compose_f_gx 。这些函数提供了用一个参数调用两个函数的方...
Boost.Lambda 支持C++中的所有算术操作符,因此几乎不再需要仅为了算术函数对象而包含
。以下例子示范了这些算术操作符中某些的用法。vector vec
中的每个元素被加法和乘法操作符...
与其它许多 Boost 库一样,这个库完全定义在头文件中,这意味着你不必构建任何东西就可以开始使用。但是,知道一点关于
lambda 表达式的东西肯定是有帮助的。接下来的章节会带你浏览一下这个库,还...
Boost.Bind 为函数和函数对象提供了一致的语法,对于值语义和指针语义也一样。我们将从一些简单的例子开始,处理一些简单绑定的用法,然后再转移到通过嵌套绑定进行函数组合。弄明白如何使用
函数组合,Part II
在SGI STL中的另一个常用的函数组合是 compose1 ,在 pose 中是
compose_f_gx 。这些函数提供了用一个参数调用两个函数的方...
他的最新文章
讲师:王哲涵
讲师:韦玮
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)}

我要回帖

更多关于 boostfunction 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信