STL编程指南/函数对象概述

函数对象 Function Objects

1. 概述

函数对象(Function Object),或者叫做仿函数Functor(这两个是同义词)是任何能够像函数一样被调用的对象。一个普通函数是一个函数对象,一个函数指针也是函数对象;更一般的讲,定义了()运算符的类的对象也是函数对象。

2. 描述

基本的函数对象的概念有Generator, Unary Function和Binary Function,它们分别表示对象可以这样调用f(), f(x)及f(x,y)。(这个列表可以很容易扩展到三元函数,甚至更多,但是实际当中,没有一个STL算法需要超过两个参数的函数对象。)STL中定义的其他关于函数对象的概念都是这三个概念的refinement。

返回bool类型的函数对象是一种重要的特例。任何返回bool类型的Unary Function被称作Predicate,返回bool类型的Binary Function被称作Binary Predicate。

在函数对象和可适配的(adaptable)函数对象之间,有一个重要的但很细微的区别。[1] 一般来说,函数对象对于其参数的类型有限制。参数类型的限制可能并不简单,operator()可以重载,可以是成员模板函数,或者两者都是。相似的,程序没有办法确定参数的限制是什么。而adaptable函数对象指定参数和返回类型是什么,并提供了内嵌的类型定义,使这些类型有确定的名字并可以在程序中使用。如果类型F0是Adaptable Generator的一个模型,那么它必须定义F0::result_type。类似的;如果F1是一个Adaptable Unary Function的模型,那么它必须定义F1::argument_type和F1::result_type;如果F2是一个Adaptable Binary Function的模型,那么它必须定义F2::first_argument_type, F2::second_argument_type和F2::result_type。STL提供了基本类型unary_function和binary_function来简化Adaptable Unary Function和Adaptable Binary Function的定义。[2]

Adaptable函数对象是很重要的,因为它们可以被函数对象适配器adaptor使用。函数对象适配器是一种能够转换或者操作其他函数对象的函数对象。STL提供了很多函数对象适配器,包括unary_negate(返回一个特定的AdaptablePredicate的逻辑非),unary_compose和binary_compose,用来组合函数对象。

最后,STL还包含了很多预定义的函数对象,包括算术运算(plus, minus, multiplies, divides, modulus和negate),比较运算(equal_to, not_equal_to greater, less, greater_equal和less_equal)和逻辑运算(logical_and, logical_or, and logical_not)。这样不用自己写新的函数对象,只要组合预定义好的的函数对象和函数对象适配器,就可以进行很复杂的运算了。

3. 例子

用随机数填充一个vector。在这个例子里面,函数对象就是一个函数指针。

   1     vector<int> V(100);
   2     generate(V.begin(), V.end(), rand);

按照绝对值给double型的vector排序,也就是说忽略元素的符号。在这个例子里面,函数对象是是一个自定义类的对象。

   1     struct less_mag : public binary_function<double, double, bool> {
   2         bool operator()(double x, double y) { return fabs(x) < fabs(y); }
   3     };
   4 
   5     vector<double> V;
   6     ...
   7     sort(V.begin(), V.end(), less_mag());

计算一个vector的元素的合。在这个例子里面,函数对象是一个带有状态的自定义类的对象。

   1     struct adder : public unary_function<double, void>
   2     {
   3       adder() : sum(0) {}
   4       double sum;
   5       void operator()(double x) { sum += x; }
   6     };
   7 
   8     vector<double> V;
   9     ...
  10     adder result = for_each(V.begin(), V.end(), adder()); [3]
  11     cout << "The sum is " << result.sum << endl;

删除一个list里面所有大于100小于1000的元素。

   1     list<int> L;
   2     ...
   3     list<int>::iterator new_end = 
   4          remove_if(L.begin(), L.end(),
   5                    compose2(logical_and<bool>(),
   6                             bind2nd(greater<int>(), 100),
   7                             bind2nd(less<int>(), 1000)));
   8     L.erase(new_end, L.end());

4. 概念

5. 类型

6. 函数

7. 备注

[1] 之所以称为"adaptable function object"可适配的函数对象,是因为它能够被函数对象适配器所使用。

[2] unary_function, binary_function和input_iterator, output_iterator, forward_iterator, bidirectional_iterator, random_access_iterator 是类似的: 它们是完全空的,只是提供了类型信息。

[3] 这只是展示如何使用函数对象的例子,并不建议这样计算vector元素的和。求和更好的方法是使用accumulate算法。

STL编程指南/函数对象概述 (2008-02-23 15:35:53由localhost编辑)