bind是一种非常神奇的存在,它不是一个单独的类或者函数,依据绑定的参数的个数和要绑定的调用对象的类型,总共有数十种不同的形式,编译器会根据具体的绑定代码制动确定要使用的正确的形式。
话不多说,直接上例子说用法。
1.bind绑定普通函数(函数指针)
定义函数
int f(int a,int b)
{
return a + b;
}
int g(int a,int b,int c)
{
return a + b + c;
}
typedef int (*f_pointer)(int,int);
typedef int (*g_pointer)(int,int,int);
调用范例
//普通函数
bind(f, 1, 2)(); //f(1,2)
bind(f, _2, _1)(x, y); // f(y, x)
bind(g, _1, 9, _1)(x); // g(x, 9, x)
bind(g, _3, _3, _3)(x, y, z); // g(z, z, z)
bind(g, _1, _1, _1)(x, y, z); // g(x, x, x)
//函数指针
f_pointer fp = f;
g_pointer gp = g;
bind(pf,_1,9); //(*pf)(x,9)
bind(pg,_3,_2,_2)(x,y,z); //(*pg)(z,y,y)
bind有两个参数表,第一个参数表是bind绑定的函数的参数表(即f和g的参数表),第二个参数表是bind生成的新的对象的参数表,其中,_1,_2…被称作占位符,至多可以有9个。
2.bind绑定成员函数
类的成员函数必须通过类的对象或者指针调用,因此在绑定时,bind要拿出第一个参数的位置来指定一个类的实例、指针或者引用。
class demo
{
public:
int f(int a,int b){return a + b;}
};
demo a,&ra = a; //类的实例对象和引用
demo * p = & a; //指针
bind(&demo::f,a,_1,20)(10); //a.f(10,20)
bind(&demo::f,ra,_2,_1)(10,20); //a.f(20,10)
bind(&demo::f,p,_1,_2)(10,20); //p->f(10,20)
注意:必须在成员函数前面加上取地址的操作符&。
再举一个例子:
bind搭配标准算法for_each用来调用容器中所有对象的print()函数
#include <boost/bind/bind.hpp>
using namespace boost;
struct point
{
int x,y;
point(int a = 0,int b = 0):x(a),y(b){}
void print()
{
cout << " ( " << x << " , " << y << " ) \n ";
}
};
int main()
{
vector<point> v(10);
for_each(v.begin(),v.end(),bind(&point::print,_1));
}
这里的for_each()函数的作用是变量v中从begin开始到end结束,每一个成员都要调用print()函数。
3.bind绑定成员变量
bind可以绑定类中的public成员变量,依然用point类来说明。
#include <boost/bind/bind.hpp>
using namespace boost;
struct point
{
int x,y;
point(int a = 0,int b = 0):x(a),y(b){}
};
int main()
{
vector<point> v(10);
vector<int> v2(10);
transform(v.begin().v.end().v2.begin(),bind(&point::x,_1));
}
该例中,transform()函数利用bind讲变量v中的成员x全部填入到变量v2中。
4.绑定函数对象
什么是函数对象?你不知道?函数对象其实是一个类的对象,只是因为这个类中重载了操作符,导致该对象调用这个操作符时,形式上看起来像个函数一样,其实它不是真的函数,不要被误导了哟。
首先来看一个函数对象的例子。
class FuncObjType
{
public:
void operator()()
{
cout<<"hello C++"<<endl;
}
}
当bind绑定函数对象时,当函数对象有内部类型定义result_type,则bind可以自动推到出返回值类型,但如果函数对象没用定义result_type,则需要用模板参数指明返回类型:bind<result_type>(functor,...);
由于boost库中大部分函数对象都有result_type,因此就可以直接使用bind,例如:
bind(std::greater<int>(),_1,10);
bind(std::plus<int>(),_1,_2);
bind(std::modulus<int>(),_1,3);
如果自定义函数对象,没有result_type的类型定义,就必须显示地在模板参数中指明bind的返回值类型:
struct func
{
int operator()(int a,int b)
{
return a + b;
}
};
cout<<bind<int>(func::obj(),_1,_2)(10,20)<<endl;
文章参考:
用法讲解:不破不立博客
工作机制探究:boost bind初步探究