C/C++编程:仿函数

1059 篇文章 280 订阅

概述

仿函数,也叫做函数对象。

  • 就实现意义而言,“函数对象”比较贴切:一种具有函数特性的对象
  • 就行为而言,“仿函数”更贴切:这种东西可以像函数一样被调用,被调用者则以对象所定义的function call operator扮演函数的实质角色

仿函数的主要作用?用来搭配STL算法

  • STL所提供的各种算法,往往有两个版本。其中一个版本表现出最常用的某种运算,第二个版本则表项出最泛化的演算流程,允许用户“以template参数来指定所要才行的策略。
    • 以accumulate为例,其第一版本将指定范围内的所有元素相加,第二版本允许你指定某种操作,取代第一版本中的“相加”行为
    • 以sort为例,其第一版本以operator<为排序时的元素位置调整依据,第二版本则运行用户指定任何“操作”,务求排序后的两两相邻的元素都能令该操作结果为true
  • 要将某种“操作当做算法的参数,有两种方法:
    • 第一种:先将“操作”设计为一个函数,再将函数指针当做算法的一个参数
    • 第二种:将“操作”设计为一个仿函数(在语言层面是一个class),再以该仿函数产生一个对象,并以此对象作为算法的一个参数
  • 那为什么不用“函数指针”而要引入仿函数呢?因为函数指针不能满足STL对抽象性的要求,也不能满足软件积木的要求:函数指针无法和STL其他组件(比如adapter)搭配,产生更灵活的变化

就实现上来看,仿函数其实是一个“行为类似函数”的对象。为了能够“行为类似函数”,其类别定义中必须自定义(或者说改写、重载)function call运算子(operator())。拥有这样的运算子之后,我们就可以在仿函数的对象后面加上一对(),以此调用仿函数定义的operator()

#include <functional>
#include <iostream>

int main(){
    std::greater<int> ig;
    std::cout << std::boolalpha << ig(4, 6) << "\n";
    std::cout <<  std::greater<int>()(4, 6);

}

在这里插入图片描述
在这里插入图片描述
STL仿函数的分类,如果以操作数的个数划分,可以为:

  • 一元仿函数
  • 二元仿函数
  • STL不支持三元仿函数

以功能划分:

  • 算术运算
  • 关系运算
  • 逻辑运算

任何应用程序想要使用STL内建的仿函数,必须引入<functional>头文件,STL将它们实际定义于<stl_functional.h>

可配接(Adaptable)的关键

在STL的六大组件中,仿函数扮演一种策略的角色,它可以让STL算法更灵活。而更灵活的关键,在于STL仿函数的可配接性。

所谓的可配接性,指的是STL 仿函数应该有能力被函数配接器修饰,彼此像积木一样串接。为了adaptable,每一个仿函数必须定义自己的相应型别。

  • 这些相应型别是为了让配接器能够取出,获得仿函数的某些信息。
  • 相应型别都只是一些typedef,所有必要操作在编译期就全部完成了,对程序的执行效率没有影响,不带来任何额外负担。
  • 仿函数的相应型别主要用来表现函数参数型别和传回值型别。为了方便起见,<stl_functional.h>定义了两个classes,分别表示一元仿函数和 二元仿函数,其中没有任何data members或者members function,唯有一些型别定义。任何仿函数,只要依个人需求选择继承其中一个class,就自动拥有了那些相应型别,也就自动拥有了配接能力

unary_function

unary_function用来表示一元函数的参数型别和返回值型别。定义如下:
在这里插入图片描述
使用如下:

// 下面仿函数继承了unary_function
template<class T>
struct negate : public std::unary_function<T, T>{
    T operator() (const T& x) const {
        return -x;
    };
};


// 下面adaptable用来表示某个仿函数的逻辑负值
template<class Predicate>
class unary_negate{
public:
    bool operator() (const typename Predicate::argument_ctype& x) const{
        
    }
};

binary_function

binary_function用来表示一元函数的第一参数型别、第二参数型别。定义如下:

在这里插入图片描述
使用如下:

// 下面仿函数继承了binary_function
template<class T>
struct plus : public std::binary_function<T, T, T>{
    T operator() (const T& x, const  T & y) const {
        return x + y;
    };
};

// 下面adaptable用来将某个二元仿函数转换为一元仿函数
template<class Operation>
class binder1st{
protected:
    Operation op;
    typename Operation::first_argument_type value;
public:
    bool operator() (const typename Operation::second_argument_type& x) const{
        
    }
};

算术仿函数

STL内建的算术类仿函数,支持加法、减法、乘法、除法、模数(余数)、否定运算。除了“否定”运算为一元运算,其他都是二元运算

在这里插入图片描述
在这里插入图片描述

使用:

#include <functional>
#include <iostream>



int main(){
    std::plus<int> plusobj;
    std::minus<int> minusobj;

    std::cout << plusobj(3, 5) << "\n";
    std::cout << minusobj(3, 5) << "\n";
    
    std::cout << std::negate<int>()(3) << "\n";
    std::cout <<  std::plus<int>()(3, 5) << "\n";
}
 std::accumulate(vec.begin(), vec.end(), std::multiplies<int>());

关系运算符

STL支持6中关系运算,每一种都是二元运算

在这里插入图片描述
定义如下:
在这里插入图片描述

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值