仿函数

       所有的仿函数定义在头文件<functional>中。

1.定义及分析

       仿函数就是一个定义了operator()的对象。

class X 
{
public:
//define "function call" operator
return-value operator() (arguments) const;
...
};
//现在这个类对象就可以当做函数一样使用
X fo;
...
fo(arg1, arg2); //call operator () for function object fo
//等同于
fo.operator() (arg1,arg2); //调用对象fo的operator()

凡是行为像函数,那么这个对象就是函数。仿函数就是这个意思,但是STL中为什么要用仿函数而不直接用函数呢?

       首先STL是一个有自己规则的框架,函数指针无法和STL其他组件搭配(配接器),产生更灵活的变化:

       仿函数应当有能力被函数配接器修饰,然后彼此合作形成一个整体。为了可配接仿函数需要定义自己的相应型别(和迭代器的型别的作用是一个含义)。由于STL只使用一元和二元仿函数,所以定义了两个class:unaru_function和binary_function。这两个类没有成员,只有一些型别定义。任何仿函数,只要依个人需求选择继承其中一个class,便自动拥有了那些相应型别,也就自动拥有了配接能力。

       其次仿函数相对于函数指针有其自身优点:

1、 仿函数是智能型函数

       就好比智能指针的行为像指针,其就可看作是一个指针。但是智能指针是定义的一个类对象,所以在具备指针功能的同时也有其他的能力。仿函数的能力也可以超越operator()。因为仿函数可以拥有成员函数和成员变量,这意味着仿函数拥有状态。另一个好处是可以在执行期初始化它们。

class AddValue 
{
private:
	int theValue; //the value to add
public:
	AddValue(int v) : theValue(v) {}
	void operator() (int& elem) const 
	{
		elem += theValue;
	}
};
AddValue addx (x); //+x
AddValue addy (y); //+y
AddValue(10))//常量
AddValue (*coll. begin())//变量

2、 仿函数都有自己的型别

       这就是泛型编程编写仿函数。

3、 仿函数通常比一般函数快

       就template的概念而言,由于更多细节在编译器就已确定,所以通常可能进行更好的最佳化。

2.预定义的仿函数

2.1算术类

       除了否定为一元,其他都为二元仿函数。

加法:plus<T>

减法:minus<T>

乘法:multiplies<T>

除法:divides<T>

求余:modulus<T>

否定:negate<T>

2.2关系运算类

       都是二元仿函数。

等于:equal_to<T>

不等于:not_equal_to<T>

大于:greater<T>

大于等于:greater_equal<T>

小于:less<T>

小于等于:less_equal<T>

2.3逻辑运算类

       与和或为二元仿函数,否为一元仿函数。

与:logical_and<T>

或:logical_or<T>

否:logical_not<T>

 

3.仿函数配接器

       仿函数配接器是配接器(仿函数、容器、迭代器)中最大的一部分。主要运用到的如以下所示:

绑定第一个参数为定值:bind1st(op,x)——效果op(x,param)

绑定第二个参数为定值:bind2nd(op,x)——效果op(param,x)

对一元仿函数逻辑取反:not1(op)——效果!op(param)

对二元仿函数逻辑取反:not2(op)——效果!op(param1,param2)

SGI版本特有的还有compose1和compose2,就是组合函数的意思:

compose1(op1,op2)——效果op1(op2())

       举例:

判定元素不小于12:bind2nd(greater_equal<int>(),12)或者not1(bind2nd(less<int>(),12))

对元素x执行(x+2)*3:compose1(bind2nd(multiplies<int>,3),bind2nd(plus<int>(),2))

      

       另外的函数配接器就是针对成员函数而设计的函数配接器:

mem_fun_ref(op)                 调用op,是某对象的一个const成员函数

men_fun(op)                        调用op,是某对象指针的一个const成员函数

注意,被men_fun_ref和men_fun调用的成员函数必须是const,C++标准库暂时不支持non-const成员函数提供函数配接器。

class Person 
{
	private:
	std::string name;
	public:
	...
	void print() const 
	{
	std::cout << name << std::endl;
	}
	void printWithPrefix (std::string prefix) const 
	{
		std::cout << prefix << name << std::endl;
	}
};
void foo (const std::vector<Person>& coll)
{
	using std::for_each;
	using std::bind2nd;
	using std::mem_fun_ref;
//对各个元素调用成员函数print
	for_each (coll.begin(), coll.end(),mem_fun_ref(&Person::print));
//对各个元素调用成员函数printWithPrefix
//-"person: "是传递的一个参数,所以使用了bind2nd
for_each (coll.begin(), coll.end(),bind2nd (mem_fun_ref (&Person::printWithPrefix),"person: "));
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值