🏭仿函数(Functor)
在详细讲常用的算法之前补充一下函数对象的相关内容,后面会用到。
函数对象 / 仿函数
重载函数调用操作符的类,其对象常称为函数对象(function object),也叫仿函数(functor),使得类对象可以像函数那样调用。
STL提供的算法往往有两个版本,一种是按照我们常规默认的运算来执行,另一种允许用户自己定义一些运算或操作,通常通过回调函数或模版参数的方式来实现,此时functor便派上了用场,特别是作为模版参数的时候,只能传类型。
函数对象超出了普通函数的概念,其内部可以拥有自己的状态(其实也就相当于函数内的static变量),可以通过成员变量的方式被记录下来。
函数对象可以作为函数的参数传递。
函数对象通常不定义构造和析构函数,所以在构造和析构时不会发生任何问题,避免了函数调用时的运行时问题。
模版函数对象使函数对象具有通用性,这也是它的优势之一。
STL需要我们提供的functor通常只有一元和二元两种。
lambda 表达式的内部实现其实也是仿函数
谓词
返回值为bool的普通函数或者函数对象,也就是我们离散数学中学习的predictor,比较常用的是一元谓词和二元谓词。
在概述中有提到过,这里再重复一下。
内建函数对象
使用时需要包含头文件
<functional>
STL 内建了一些函数对象,分为:
算术类函数对象
关系运算类函数对象
逻辑运算类函数对象
算术类函数对象
negate 是一元运算,其他都是二元运算。
关系运算类函数对象
逻辑运算类运算函数
适配器
为了方便理解,我们以例子的形式来讲述这个部分的内容。
函数对象适配器
原程序
新需求
我们希望在每个数据输出的时候加上一个基值,并且该基值由用户输入。
使用函数适配器做的改进
取反适配器
原程序
新需求
我们希望找第一个不大于5的数,但又不想再写一个LessEqualThanFive。
使用取反适配器做的改进
其实综合前面的内容会有更简便的方法:
这一行代码如果还半知半解的话还请驻足思考一番,思考透彻了上述内容才算是真的懂了。
函数指针适配器
沿用函数对象适配器的例子,假设myPrint是一个全局函数
成员函数适配器
我们假设有一个Dog类,Dog类内部有一个bark()成员方法,有一个装满了Dog的vector叫做v。
偏函数
对于一个多参数的函数,在某些应用场景下,它的一些参数往往取固定值,可以针对这样的函数,生成一个新函数,该新函数不包含原函数中已指定固定值的参数。(partial function application, 偏函数)
偏函数可缩小一个函数的适用范围,提高函数的针对性
例如,对于下面的print函数:
由于它常常用来按十进制输出,因此,可以基于print生成一个新函数print10,只接受一个参数n,base固定为10:
至此,读者应当对于仿函数/函数对象有了一个稍微深入一点的理解了。如果还觉得有些云里雾里的话也没关系,以后熟悉了就好了。
最后更新于
这有帮助吗?