时间:2021-05-20
如果一个类将()运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象。函数对象是一个对象,但是使用的形式看起来像函数调用,实际上也执行了函数调用,因而得名。
下面是一个函数对象的例子。
程序的输出结果是:
2. 66667
()是目数不限的运算符,因此重载为成员函数时,有多少个参数都可以。
average 是一个对象,average(3, 2, 3) 实际上就是 average.operator(3, 2, 3),这使得 average 看上去像函数的名字,故称其为函数对象。
STL 中有以下实现“累加”功能的算法(函数模板):
该模板的功能是对 [first, last) 中的每个迭代器 I 执行 val = op(val, *I),返回最终的 val。在 Dev C++ 中,numeric 头文件中 accumulate 的源代码如下:
此模板被实例化后,op(init, *first)必须要有定义,则 op 只能是函数指针或者函数对象。因此调用该 accmulate 模板时,形参 op 对应的实参只能是函数名、函数指针或者函数对象。
下面的程序通过 accumulate 模板求一个 vector 中元素的平方和,其中用到了函数对象。
程序的输出结果如下:
1)1 2 3 4 5 6 7 8 9 10
2)平方和:385
3)立方和3025
4)4次方和:25333
第 37 行,第四个参数是 SumSquares 函数的名字。函数名字的类型是函数指针,因此本行将 accumulate 模板实例化后得到的模板函数定义如下:
形参 op 是一个函数指针,而op(init, *first)就调用了指针 op 指向的函数,在第 37 行的情况下就是函数 SumSquares。
第 39 行,第四个参数是 SumPowers<int>(3)。SumPowers 是类模板的名字,SumPowers<int> 就是类的名字。类的名字后面跟着构造函数的参数列表,就代表一个临时对象。因此 SumPowers<int>(3) 就是一个 SumPowers<int> 类的临时对象。
编译器在编译此行时,会将 accumulate 模板实例化成以下函数:
形参 op 是一个函数对象,而op(init, *first)等价于:
即调用了 SumPowers<int> 类的 operator() 成员函数。
对比 SumPowers 和 SumSquares 可以发现,函数对象的 operator() 成员函数可以根据对象内部的不同状态执行不同操作,而普通函数就无法做到这一点。因此函数对象的功能比普通函数更强大。
STL 中的排序模板 sort 能将区间从小到大排序。sort 算法有两个版本。第一个版本的原型如下:
该模板可以用来将区间 [first, last) 中的元素从小到大排序,要求 first、last 是随机访问迭代器。元素比较大小是用<进行的。如果表达式a<b的值为 true,则 a 排在 b 前面;如果a<b的值为 false,则 b 未必排在 a 前面,还要看b<a是否成立,成立的话 b 才排在 a 前面。要使用这个版本的 sort 算法,待排序的对象必须能用<运算符进行比较。
sort 算法第二个版本的原型如下:
这个版本和第一个版本的差别在于,元素 a、b 比较大小是通过表达式op(a, b)进行的。如果该表达式的值为 true,则 a 比 b 小;如果该表达式的值为 false,也不能认为 b 比 a 小,还要看op(b, a)的值。总之,op 定义了元素比较大小的规则。下面是一个使用 sort 算法的例子。
编译至第 45 行时,编译器将 sort 实例化得到的函数原型如下:
该函数在执行过程中,当要比较两个元素 a、b 的大小时,就是看 op(a, b) 和 op(b, a) 的返回值。本程序中 op 指向 GreaterA,因此就用 GreaterA 定义的规则来比较大小。
编译至第 47 行时,编译器将 sort 实例化得到的函数原型如下:
该函数在执行过程中,当要比较两个元素 a、b 的大小时,就是看 op(a, b) 和 op(b, a) 的返回值。本程序中,op(a, b) 等价于 op.opeartor(a, b),因此就用 LessA 定义的规则来比较大小。
STL 中定义了一些函数对象类模板,都位于头文件 functional 中。例如,greater 模板的源代码如下:
假设有以下数组:
要将该数组从大到小排序,则只需写:
要使用 greater 模板,须确保>运算符本来就有定义,或经过了适当的重载。
list 容器的 sort 成员能将元素从小到大排序。它也有两个版本:一个是没有参数的函数,比较大小用<运算符;另一个是函数模板,原型如下:
sort 函数允许自定义比较大小的规则,即 op(x, y) 为真就认为 x 比 y 小。例如,假设有:
如果希望将 lst 中的元素按其整数数值从大到小排序,只需写:
在使用关联容器和许多算法时,都可以用函数对象来定义比较大小的规则,以及其他一些规则和操作。
STL 中有一些函数对象类模板,如表 1 所示。
表1:STL 中的函数对象类模板
函数对象类模板 成员函数T operator ( const T &x, const T &y) 的功能 plus <T> return x + y; minus <> return x - y; multiplies <T> return x * y; divides <T> return x / y; modulus <T> return x % y; 成员函数bool operator( const T &x, const T &y) 的功能 equal_to <T> return x == y; not_equal_to <T> return x! = y; greater <T> return x >y; less <T> return x <y; greater_equal <T> return x >= y; less_equal <T> return x <= y; logical_and <T> return x &&y; logical_or <T> return x ||y; 成员函数 T operator( const T &x) 的功能 negate <T> return - x; 成员函数bool operator( const T &x) 的功能 logical_not <T> return ! x;
例如,如果要求两个 double 型变量 x、y 的乘积,可以写:
less 是 STL 中最常用的函数对象类模板,其定义如下:
要判断两个 int 变量 x、y 中 x 是否比 y 小,可以写:
前面提到过,默认情况下,STL 中的容器和算法比较元素的大小是通过<运算符进行的。通过 10.3.4 节可知,sort 和 list::sort 都可以通过一个函数对象或函数自定义比较元素大小的规则。例如以下的 sort 版本:
实际调用 sort 时,和 op 对应的实参可以是一个函数对象或者函数的名字。sort 在执行过程中用 op(x, y) 比较 x 和 y 的大小,因此可以将 op 称为自定义的“比较器”。
关联容器中的元素是从小到大排序的。使用关联容器时,也可以用自定义的比较器取代<运算符,以规定元素之间的大小关系。STL 中还有许多算法都可以自定义比较器。在自定义比较器 op 的情况下,以下三种说法是等价的:
同样地,对关联容器的 find 和 count 成员函数以及其他一些在有序区间上的 STL 算法而言,在自定义比较器 op 的情况下,x和y相等与op(x, y)和op(y, x)都为假是等价的。
到此这篇关于C++函数对象详解附带实例的文章就介绍到这了,更多相关C++ 函数对象内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
C++中const对象与const成员函数的实例详解const对象只能调用const成员函数:#includeusingnamespacestd;classA{
C++中构造函数的实例详解c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++
C++中函数重载、覆盖与隐藏详解在C++语言中,函数扮演着很重要的角色,不管面向过程设计,还是基于对象设计;不管是面向对象编程,还是基于泛型编程,函数都可以随处
C++中const修饰虚函数实例详解【1】程序1#includeusingnamespacestd;classBase{public:virtualvoidpr
C/C++如何获取当前系统时间的实例详解C库中与系统时间相关的函数定义在头文件中,C++定义在头文件中。一、time(time_t*)函数函数定义如下:time