Boost库-功能介绍-Boost::bind对象-函数接口参数修改


  bind接收的第一个参数必须是一个可调用的对象f,包括函数、函数指针、函数对象、和成员函数指针,之后bind最多接受9个参数,参数数量必须与f的参数数量相等,这些参数被传递给f作为入参。 绑定完成后,bind会返回一个函数对象,它内部保存了f的拷贝,具有operator(),返回值类型被自动推导为f的返回类型。在发生调用时这个函数对象将把之前存储的参数转发给f完成调用。bind实现的主要功能就是修改调用接口的参数调用形式,并返回新的调用对象供使用,实际上实现的就是转接功能。

void function(int a1,int a2);

function(a1,a2);
//等价于
bind(function,a1,a2)();

  这是bind最简单的形式,bind表达式存储了func和a1、a2的拷贝,产生了一个临时函数对象。因为func接收两个参数,而a1和a2的拷贝传递给func完成真正的函数调用。
  而bind的真正威力在于它的占位符,它们分别定义为_1,_2,_3,一直到 _9,位于一个匿名的名字空间。占位符可以取代bind参数的位置,在发生调用时才接受真正的参数。占位符的名字表示它在调用式中的顺序,而在绑定的表达式中没有没有顺序的要求,_1不一定必须第一个出现,也不一定只出现一次,例如:

bind(function,_2,_1)(a1,a2);
//等价于
func(a2,a1);

int f(int a,int b){return a+b;}   //二元函数
int g(int a,int b,int c) {return a+b+c;} //三元函数

bind(f,_1,9)(x);  //f(x,9),相当于bind2nd(f,9)
bind(f,_1,_2)(x,y); //f(x,y)
bind(f,_2,_1)(x,y); //f(y,x)
bind(f,_1,_1)(x,y); //f(x,x),y参数被忽略
bind(g,_1,8,_2)(x,y) //g(x,8,y)
bind(g,_3,_2_2)(x,y,z) //g(z,y,y),x参数被忽略

  必须在绑定表达式中提供函数要求的所有参数,无论是真实参数还是占位符均可以。占位符可以出现也可以不出现,出现的顺序和数量没有限定,但不能使用超过函数参数数量的占位符,比如在绑定f是不能用_3,在绑定g时不能使用_4,也不能写bind(f,_1,_2,_2),这样的形式会导致编译错误。bind也可以绑定函数指针,用法相同。

使用举例:

1.全局函数

  如上所示。

2.成员函数

  类的成员函数不同于普通的函数,因为成员函数指针不能直接调用operator(),它必须被绑定到一个对象或指针,然后才能得到this指针进而调用成员函数。因此bind需要 “牺牲”一个占位符,要求提供一个类的实例、引用或者指针,通过对象作为第一个参数来调用成员函数,范例代码如下:

//形式
bind(&Class::function,ClassObject,_1,_2,)

struct Class1
{
    int f(int a,int b){return a+b;}
};

//执行代码
Class1 class1Object;
std::cout<<bind(&Class1::f,class1Object,_2,_1)(10,20)<<std::endl;

  【注意】必须在成员函数前面加上取地址的操作符&,表明这是一个成员函数指针,否则会无法编译通过,这是与绑定函数的一个小小的不同。bind同样支持绑定虚拟成员函数,用法与非虚函数相同,虚函数的行为将由实际调用发生时的实例来决定。

3.成员变量

  bind的另一个对类的操作是它可以绑定public成员变量,用法与绑定成员函数类似,把成员变量名转化为一个空参数的成员函数一样去使用。范例如下:

#include <iostream>
#include <string>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>

typedef struct Point
{
	int x;
	int y;
}Point;

int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<Point> v(10);
	BOOST_FOREACH(Point& pt, v)
	{
		pt.x = 1;
		pt.y = 2;
	}
	std::vector<int> v2(10);
	std::transform(v.begin(), v.end(), v2.begin(), boost::bind(&Point::x, _1));
	BOOST_FOREACH(int val, v2)
	{
		std::cout << val << "," << std::endl;
	}

	//取对象成员
	std::cout << boost::bind(&Point::y, v[0])() << std::endl;
	typedef std::pair<int, std::string> pair_t;
	pair_t p(123, "str");
	std::cout << boost::bind(&pair_t::first, p)() << std::endl;
	std::cout << boost::bind(&pair_t::second, p)() << std::endl;
	return 0;
}

4.函数对象

  bind不仅能够绑定函数和函数指针,也能够绑定任意的函数对象,包括标准库中预定义的函数对象。如果函数对象有内部类型定义result_type,那么bind可以自动推导出返回值类型,用法与普通函数一样。但如果函数对象没有定义result_type,则需要在绑定形式上做一点改动,用模板参数指明返回类型,范例如下:

bind<result_type>(Functor,);//指明返回类型

//标准库和Boost库中的大部分函数都具有result_type定义,因此不需要特别的形式就可以直接使用bind,例如:
boost::bind(std::greater<int>(),_1,10);  //检查 x>10
boost::bind(std::plus<int>(),_1,_2); //执行 x+y
boost::bind(std::modulus<int>(),_1,3), //执行 x%3

//对于自定义的函数对象,如果没有result_type类型定义,需指明返回类型
struct f
{
	int operator() (int a,int b) {return a +b;}
};
boost::bind<int> (f(),_1,_2)(10,20)<<std::endl;

5.保存表达式

  可以采用BOOST_AUTO来创建一个同样功能的bind表达式函数对象。代码如下:

BOOST_AUTO(t,bind(std::greater<int>(),_1,_2));
cout<<t(10,20)<<endl;

6.作者答疑

  如有疑问,请留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值