函数对象的意义:泛型算法应用以及避免重载带来的全局影响
今天终于想到了函数对象的意义了
函数对象就是重载了()的类对象,他的第一个意义,C++ Primer讲的很清楚,更加灵活的在泛型算法中使用:
举个例子:
如果我们想对一个序列a(成员可能是非基本变量类型)排序,可以使用以下几种方法:
==========================================================================
方法一:重载<
如果变量没有重载操作符<,手动重载,然后调用sort(a.begin(),a.end());
如果希望从大到小排序,在重载操作符<的时候,实际返回的是操作>比较的结果,就可以了
==========================================================================
当然,如果a是int类型,或者其他不适宜重载操作符<的类型,却又想逆向排序(相对于正常<生成的排序结果来说
),只能使用第二种的方法了
方法二:定义比较函数
如果没有重载<,或者不希望按照<,所给的逻辑顺序排序,可以手动指定比较函数
sort(a.begin(),a.end(),cmp);
cmp的函数原型应该是:
bool cmp(const Type &a,const Type &b);
==========================================================================
当然,如果我已经重载了操作符<,操作符>,在排序的时候,我希望用>来排序,即从大到小,是不是只能使用第二
种方法呢?当然有更简便的方法:
方法三:使用函数对象
函数对象就是重载了()的类对象,使用起来和函数很像,例如
struct cmp
{
bool operator() ( Node a, Node b )
{
if( a.x== b.x ) return a.y> b.y;
return a.x> b.x;
}
}
可以在第二种方法中调用sort一样,将cmp带入第三个参数,效果是一样的,貌似在这里看不到有啥好处吧,和第
二个不是一样的么?好处体现在,使用了C++标准库STL提供的 函数对象之后(定义在<functional>头):
有很多,基本所有的操作符都有对应的,就先举两个例子吧:
great<Type> 对应>
less<Type> 对应<
相当于生成一个函数对象,操作符()函数返回的分别是>和<的结果,所以第三种方法写出来的应该是这样:
sort(a.begin(),a.end(),less<Type>); 从小到大 (Type为a的类型)
sort(a.begin(),a.end(),greater<Type>); 从大到小 (Type为a的类型)
========================================================================
最后,为什么,函数对象的意义包括避免重载带来的全局影响?
其实,也可是说是第二种方法的意义,因为如果为了得到逆向排序而重载,“逻辑错误”的<,可能导致诸多问题。
对后来程序的书写带来麻烦,所以建议使用后面的2种方法,避免带来全局影响
函数对象还有一个好处,C++ primer说过了,就是相当于设定函数参数这样的,很灵活,详细参考《C++ Primer
中文第四版》 P450-P453
英文原版 P531-P534