Page cover

🏭仿函数(Functor)

在详细讲常用的算法之前补充一下函数对象的相关内容,后面会用到。

函数对象 / 仿函数

  1. 重载函数调用操作符的类,其对象常称为函数对象(function object),也叫仿函数(functor),使得类对象可以像函数那样调用。

  2. STL提供的算法往往有两个版本,一种是按照我们常规默认的运算来执行,另一种允许用户自己定义一些运算或操作,通常通过回调函数或模版参数的方式来实现,此时functor便派上了用场,特别是作为模版参数的时候,只能传类型。

  3. 函数对象超出了普通函数的概念,其内部可以拥有自己的状态(其实也就相当于函数内的static变量),可以通过成员变量的方式被记录下来。

  4. 函数对象可以作为函数的参数传递。

  5. 函数对象通常不定义构造和析构函数,所以在构造和析构时不会发生任何问题,避免了函数调用时的运行时问题。

  6. 模版函数对象使函数对象具有通用性,这也是它的优势之一。

  7. STL需要我们提供的functor通常只有一元和二元两种。

  8. lambda 表达式的内部实现其实也是仿函数

谓词

返回值为bool的普通函数或者函数对象,也就是我们离散数学中学习的predictor,比较常用的是一元谓词和二元谓词。

在概述中有提到过,这里再重复一下。

内建函数对象

使用时需要包含头文件<functional>

STL 内建了一些函数对象,分为:

  • 算术类函数对象

  • 关系运算类函数对象

  • 逻辑运算类函数对象

算术类函数对象

negate 是一元运算,其他都是二元运算。

关系运算类函数对象

逻辑运算类运算函数

适配器

为了方便理解,我们以例子的形式来讲述这个部分的内容。

函数对象适配器

原程序

新需求

我们希望在每个数据输出的时候加上一个基值,并且该基值由用户输入。

使用函数适配器做的改进

取反适配器

原程序

新需求

我们希望找第一个不大于5的数,但又不想再写一个LessEqualThanFive。

使用取反适配器做的改进

其实综合前面的内容会有更简便的方法:

函数指针适配器

沿用函数对象适配器的例子,假设myPrint是一个全局函数

成员函数适配器

我们假设有一个Dog类,Dog类内部有一个bark()成员方法,有一个装满了Dogvector叫做v

偏函数

对于一个多参数的函数,在某些应用场景下,它的一些参数往往取固定值,可以针对这样的函数,生成一个新函数,该新函数不包含原函数中已指定固定值的参数。(partial function application, 偏函数)

  • 偏函数可缩小一个函数的适用范围,提高函数的针对性

例如,对于下面的print函数:

由于它常常用来按十进制输出,因此,可以基于print生成一个新函数print10,只接受一个参数n,base固定为10:

function类和bind的使用需要c++11标准

最后更新于

这有帮助吗?