[Boost基础]函数与回调――bind绑定(一)

2014-11-24 08:23:48 · 作者: · 浏览: 0
[cpp]
#pragma once
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace boost;
//bind是C++98标准库中函数适配器bind1st、bind2nd的泛化和增强,可以适配任意的可调用对象,包括函数,函数指针,函数引用,成员函数指针和函数对象。bind远远的超越了STL中的函数绑定其(bind1st/bind2nd),可以绑定最多9个函数参数,而且对绑定对象的要求很低,可以在没有result_type内部类型定义的情况下完成对函数对象的绑定。bind库很好的增强了标准库的功能。
//绑定普通函数(函数,函数指针)
int f(int a,int b){return a+b;}//二元函数
int g(int a,int b,int c){return a+b*c;}//三元函数
void test1()
{
//绑定表达式没有使用占位符
cout<
cout<
cout<
//使用占位符
int x=0,y=1,z=2;
cout<>f(x,9)
cout<>f(x,y)
cout<>f(y,x)
cout<>f(x,x);y参数被忽略了
cout<>g(x,8,y)
cout<>g(z,y,y);x参数被忽略了
//必须在绑定表达式中提供函数要求的所有参数,无论是真实参数还是占位符均可以。但不能使用超过函数参数数量的占位符,eg:在绑定f是不能使用_3;在绑定g是不能使用_4;也不能写bind(f,_1,_2,_2)这样的形式,否则会导致编译错误
}
//绑定函数指针 用法同上,可以还有占位符,也可以不使用占位符
typedef int (*f_type)(int,int);//函数指针定义
typedef int(*g_type)(int,int,int);//函数指针定义
void test2()
{
f_type pf=f;
g_type pg=g;
int x=1,y=2,z=3;
cout<>(*pf)(x,9)
cout<>(*pg)(z,y,y)
}
//绑定成员函数
void test3()
{ //类的成员函数不同于普通函数,因为成员函数指针不能直接调用opreator(),它必须被绑定到一个对象或者指针上,然后才能得到this指针进而调用成员函数。因此bind需要牺牲一个占位符的位置(意味着使用成员函数是只能最多绑定8个参数),要求用户提供一个类的实例,引用或者指针,通过对象最为第一个参数来调用成员函数。
struct demo//使用struct仅仅是为了方便,不必写出public
{
int f(int a,int b){return a+b;}
};
demo a,&ra=a,*p=&a;//类的实例对象,引用,指针
cout<>a.f(10,20)
cout<
>ra.f(20,10)
cout<p->f(10,20)
//注意:我们必须在成员函数前加上取地址操作符&,表明这是一个成员函数指针,否则会无法通过编译,这是与绑定函数的一个小小的不同。
//bind能够绑定成员函数,这是个非常有用的功能,它可以代替标准库中令人迷惑的mem_fun和mem_fun_ref绑定器,用来配合标准算法操作容器中的对象。下面试使用bind搭配标准算法for_each用来调用容器中所有对象的print()函数:
struct point
{
int x,y;
point(int a=0,int b=0):x(a),y(b){}
void print(){cout<<"("<
};
vectorv(2,3);
for_each(v.begin(),v.end(),bind(&point::print,_1));
//(3,0) (3,0)
//bind同样支持绑定虚拟成员函数,用法与非虚拟成员函数相同,虚函数的行为将有实际调用发生时的实例来决定。
}
//绑定函数对象
void test4()
{
//如果函数对象有内部类型定义result_type,那么bind可以自动推导出返回值的类型,用法与绑定普通函数一样。但如果函数对象没有定义result_type,则需要在绑定形式上做一点改动,用模板参数指明返回类型,eg bind(Functor,...)
//标准库和boost库中大部分函数对象都具有result_type定义,因此不需要特别的形式就可以直接使用bind
int x=5,y=2;
//cout<(),_1,10)(x)<10
//cout<(),_1,_2)(x,y)<
//cout<(),_1,3)(x)<
//上面三行在vs2010中没问题,但在vs2008中有问题
//对于自定义函数对象,如果没有result_type类型定义,eg
struct f
{
int operator()(int a,int b)
{ return a+b;}
};
cout<(f(),_1,_2)(x,y)<
//这种写法多少会有些不方便,因此,在编写自己的函数对象是,最好遵循规范为它们增加内部typedef result_type,这样将使函数对象与许多其他标准库和boost库 组件良好配合工作。
}
//绑定成员变量
void test5()
{
struct point
{
int x,y;
point(int a=0,int b=0):x(a),y(b){}
void print(){cout<<"("<
};
vectorv(2,3);
vectorv2(2);
transform(v.begin(),v.end(),v2.begin(),bind(&point::x,_1));
}
//使用ref库
void test6()
{//bind采用拷贝的方式存储绑定对象和参数,这意味着绑定表达式中的每个变量都会有一份拷贝,如果函数对象或值参数很大,拷贝代价很高,或者无法拷贝,那么bind的使用就会受到限制。因此bind库可以搭配ref库使用,ref库包装了对象的引用,可以让bind存储对象引用实例,从而降低了拷贝的代价。(必须包装引用的对象存在,其没有销毁)
in