袁小凯
华南理工大学计算机研究所北区研发二部
Email – [email protected]
前言
在使用STL进行程序设计时,你会经常用到Function Object,尤其是在写一个泛型算法并充许把行为参数化时。Function Object简单点讲分两种:1.函数指针(最简单的Function Object)。2.class形式的Function Object。
1. 函数指针(最简单的Function Object)函数指针指向一个函数,指向的函数一般为全局函数。通过函指针可以使行为参数化。
int a[5]={1,2,3,4,5};
vector<int> obj(a,a+5);
find_if(a,a+5,equalcmp); //找出第一个等于5的元素
这里的equalcmp是一个函数指针,它指向一个全局函数equalcmp。
bool equalcmp (int x){return x==5;}
这里通过传入函数指针使得我们可以使算法find_if按照我们定义的行为进行查找。
2. class 形式的Function Object简单点说就是定义了operator () 成员函数的类。这样的类可以像函数一样进行调用,如果说 equalcmp 就是这样一个类,ecfo是其一个对象,则可进行如下函数呼叫动作:
ecfo(); //类似无参的函式呼叫,当然也以有参数。
还拿前面的例子来说,把equal_5定义成class形式的Funtion Object,如下:
struct equalcmp
{
equalcmp(int x=5):data(x){}
bool operator () (int x){return data==x;}
int data;
};
定义了equalcmp后我们可以利用它来进行find_if查询。
find_if(a,a+5,equalcmp(5)); //找出第一个等于5的元素
它的行为个前面的一样,注意equalcmp(5)的形式,它是用于产生一个临时的equalcmp对象,得以调用operator ()成员函数。
3.两者的比较函数指针形式的functor(Function Object的另一种叫法)好像不够灵活,因为如果equalcmp不找等于5的元素了,换找4,它不能用了。你是改那,还是重写一个。哈哈!但class形式的functor(写起来方便多了^_^)可以减少这种无聊的重复劳动。换找4!,不就是找4吗,没问题。
find_if(a,a+5,equalcmp(4));
搞定!简单,方便,好用。如果用函数指标来实现这种功能可有些困难,因为无法存储局部状态,如果要实现可能需要全局变量。如果需要多个这样的functor会需要多个全局变量,不是尽量不要用全局变量吗?一些专家的忠告。但是还是有些人会固执认为类functor会效率的问题,因为要构造和析构。它们在寻求一种解决方法,他们可能找到了一种如下的方法:
template<int N>
bool equalcmp(int x)
{ return x==N; }
find_if(a,a+5,equalcmp<4>(4));//找4,VC(X),G++2.91.57(X),CB(O)
请问这种方法能行吗?你试过吗?如果没试试吧!这在某些编译器上可以,有些不行。但绝对可以这样调用equalcmp<4>(4);如果曾经这样调用过再这样使用find_if(a,a+5,equalcmp<4>(4))是可以的。可能是编译器产生Function Template实体时机的问题。
假设这样做可以,但是这不够一般化。你可使用类的形式写出更一般化的functor,可以满足所有的数据类型。
template <class T>
struct equalcmp
{
equalcmp(T x=5):data(x){}
bool operator () (T x){return data==x;}
T data;
};
find_if(a,a+5,equalcmp<int>(4));
现在equalcmp可以使用任意数据类型,这一下使用函数指针可没法完成了吧!因为你写不出这样的函数来让它指。哈哈!松口气先,再喝口水。还有函数指针没法用Adaptable Function Object,因为它无进行嵌套定义数据类型。太多函数指针无法完成动作了。那是不是函数指针就没有用了呢?不是,当你已经有了一个函数可用,那你就可以用函数指针,而不用重写一个class形式的functor。还有函数指针也可通过Function Object Adaptor转换成Adaptable Function Object。就说这么多吧!
总之!如果你没有现成的函数可用,请定义class形式的Function Object。
后语:该文是我个人的学习总结,如果有什么错误请大家指正。
本文地址:http://com.8s8s.com/it/it29808.htm