[Boost基础]函数与回调——bind绑定
[cpp]#pragma once#include <boost/bind.hpp>#include <string>#include <iostream>#include <conio.h>#include <vector>#include <algorithm>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<<bind(f,1,2)()<<endl;//3 bind(f,1,2)返回一无参调用的函数对象,等价于f(1,2)cout<<bind(g,1,2,3)()<<endl;//7 同上cout<<f(1,2)<<" "<<g(1,2,3)<<endl;//3 7//使用占位符int x=0,y=1,z=2;cout<<bind(f,_1,9)(x)<<endl;//9 ==>>f(x,9)cout<<bind(f,_1,_2)(x,y)<<endl;//1 ==>>f(x,y)cout<<bind(f,_2,_1)(x,y)<<endl;//1 ==>>f(y,x)cout<<bind(f,_1,_1)(x,y)<<endl;//0 ==>>f(x,x);y参数被忽略了cout<<bind(g,_1,8,_2)(x,y)<<endl;//8 ==>>g(x,8,y)cout<<bind(g,_3,_2,_2)(x,y,z)<<endl;//3 ==>>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<<bind(pf,_1,9)(x)<<endl;//10 ==>>(*pf)(x,9)cout<<bind(pg,_3,_2,_2)(x,y,z)<<endl;//7 ==>>(*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<<bind(&demo::f,a,_1,20)(10)<<endl;//30 ==>>a.f(10,20)cout<<bind(&demo::f,ra,_2,_1)(10,20)<<endl;//30 ==>>ra.f(20,10)cout<<bind(&demo::f,p,_1,_2)(10,20)<<endl;//30 ==>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<<"("<<x<<","<<y<<") ";}};vector<point>v(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<result_type>(Functor,...)//标准库和boost库中大部分函数对象都具有result_type定义,因此不需要特别的形式就可以直接使用bindint x=5,y=2;//cout<<bind(greater<int>(),_1,10)(x)<<endl;//0 检查x>10//cout<<bind(plus<int>(),_1,_2)(x,y)<<endl;//7 执行x+y//cout<<bind(modulus<int>(),_1,3)(x)<<endl;//2 执行 x%3//上面三行在vs2010中没问题,但在vs2008中有问题//对于自定义函数对象,如果没有result_type类型定义,egstruct f{int operator()(int a,int b){ return a+b;}};cout<<bind<int>(f(),_1,_2)(x,y)<<endl;//7//这种写法多少会有些不方便,因此,在编写自己的函数对象是,最好遵循规范为它们增加内部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<<"("<<x<<","<<y<<") ";}};vector<point>v(2,3);vector<int>v2(2);transform(v.begin(),v.end(),v2.begin(),bind(&point::x,_1));}//使用ref库void test6(){//bind采用拷贝的方式存储绑定对象和参数,这意味着绑定表达式中的每个变量都会有一份拷贝,如果函数对象或值参数很大,拷贝代价很高,或者无法拷贝,那么bind的使用就会受到限制。因此bind库可以搭配ref库使用,ref库包装了对象的引用,可以让bind存储对象引用实例,从而降低了拷贝的代价。(必须补充:软件开发 , C++ ,
上一个:c++标准模板库容器分类
下一个:POJ 3009 Curling 2.0
- 更多C/C++疑问解答:
- 关于c++的cout输出的问题。
- 在学校里学过C和C++,不过学的很一般,现在自学C#,会不会很难?
- 全国计算机二级C语言笔试题
- 已知某树有2个2度结点,3个3度结点,4个4度结点,问有几个叶子结点?
- c++数据结构内部排序问题,整数排序
- 2012九月计算机二级C语言全国题库,,急求急求
- 如果assert只有一个字符串作为参数,是什么意思呢?
- C语言中,哪些运算符具有左结合性,哪些具有右结合性,帮忙总结下,谢谢了!
- 为什么用结构体编写的程序输入是,0输不出来啊~~~
- 将IEEE—754的十六进制转化为十进制浮点类型,用C或C++都行,多谢各位大侠啊,非常感谢!
- 为什么这个程序求不出公式?
- 这个链表倒置的算法请大家分析下
- c语言函数库调用
- C语言unsigned int纠错
- C语言快排求解啊