C++中的仿函数Functor

在C++中,有仿函数Functor的概念,首先要明白,它叫做仿函数,就说明它本身肯定不是一个函数 => 事实上,它是一个类的对象,但是可以像函数一样来进行调用

怎么来理解这句话呢 “仿函数是一个类的对象,但是它可以像函数一样来进行调用”? 

是这样的 => 本质是在这个类里面实现一个operator(), 实现这个operator之后呢,这个类就有了类似函数的行为, 此时实例化这个类的一个对象时,我们可以像调用函数一样来调用类的这个实例化对象。  =>  这个类就叫做 仿函数类

我们来看一个很直观的例子:

 

复制代码
class TestAdd
{
    public:
        int operator()(int x, int y) const  // 类 TestAdd中实现了operator, 它就是一个方法函数类,operator操作符可以接受任意数量和类型的参数,还可以有返回值
        {
                return x + y;
         }
};

int main()
{
      TestAdd add;  // 创建类TestAdd的一个实例化对象 add

      int addResult = add(1,2); //像调用函数一样去调用这个仿函数类的对象add

      std::count <<  "Result: " << addResult << std::end1;

     return 0;
}
复制代码

我们再来看另一个仿函数operator的类子

复制代码
Class Point
{
  public:
     Point() { _a = _b = 1; }
     
      //在类Point中定义仿函数操作符operator
     Point &operator() (int aa, int bb)
    {
         _a += aa;
         _b += bb;

         return *this;
    }


  private:
   
    int _a, _b;
}

int main()
{
     Point pt;
     pt(4,5);

     return 0;
}
复制代码

 

 现在,我们来重点说一下,仿函数类中的重载运算符operator()  => operator()函数运算符重载

C++中,仿函数类中重载的operator()函数是仿函数的关键部分,它使得这个类对象可以像函数一样被调用. 通过重载operator()函数,我们可以来定义仿函数类的行为,使它在被调用时执行特定的操作

operator()函数的作用

     operator()函数是仿函数类中的函数调用运算符, 它决定了仿函数对象在被调用时的行为

     当我们像调用函数一样调用(使用)仿函数对象时, 实际上是在调用该仿函数类对象中重载的operator()函数

operator()函数的语法

    operator()函数的语法类似于普通成员函数的语法,但是函数名是operator()

    一般情况下,operator()函数可以被重载为const成员函数,以确保对象的状态不被修改

operator()函数的参数和返回值

   operator()函数可以接受任意数量和类型的参数

   operator()函数可以定义返回值,可以根据需求返回不同类型的值

 

仿函数重载运算符operator()除了可以在类里面使用外,也可以在结构体struct里面进行使用

 

最后,我们来看一下仿函数在C++中最大的应用  => 仿函数在STL中的使用,它是STL六大组件之一

接下来我们主要是想讲讲仿函数的使用,仿函数的使用主要是在STL中,包括以下3点

1. 仿函数在使用时,可以像普通函数那样使用,可以有参数,可以有返回值

2. 仿函数超出普通函数的概念,仿函数对象(本质是实现了operator的类对象)可以有自己的状态

3. 仿函数可以作为参数传递  => 这个是仿函数最大的使用

在多数的使用场景中,仿函数最大的用处是作为参数传递, 我们来看一个例子

复制代码
#include<string>

//1. 仿函数在使用时,函数对象可以像普通函数那样调用,可以有参数和返回值
class TestAdd
{
    int operator()(int a, int b)
    {
         return a + b;
    }
}

void testFunctor1()
{
    TestAdd testAdd;

    //下面的cout语句中,对仿函数进行调用,它本质上就是类对象在调用重载的operator函数
     cout << testAdd(5,5) <<end1;
}


//2. 仿函数可以有自己的状态
class TestState
{
     public:
         TestState()
         {
               count = 0;
         }
         void operator()(string str)
         {
               cout << str <<end1;
               count++;   //统计状态次数
         }
   
         int count; //内部自己的状态
}

void testFunctor2()
{
    TestState testState;
    testState("I am from China");
    testState("I am from China");
    testState("I am from China");
    cout << "testState的调用次数: " << testState.count << end1;
}

//3. 最大的应用,仿函数对象可以作为参数传递
void FunctorAsArg(TestState &tState, string testValue)
{
        tState(testValue);
}

void testFunctor3()
{
     TestState testState;
     FunctorAsArg(testState, "Learn C_++");
}
复制代码

 

仿函数中的谓词概念

在仿函数中,有一种仿函数称为谓词,就是返回值为bool类型的仿函数称为谓词, 如果operator()接受一个参数,就是一元谓词,如果operator()接受2个参数,就是2元谓词

谓词最常用的地方,和仿函数最常用的地方一样,都是作为函数的参数传递使用,谓词最常用的地方就是在STL算法中作为参数使用

一元谓词

复制代码
#include<vector>
#include<algorithm>

// 一元谓词
class GreaterThanOne
{
    public:
      bool operator()(int val)
      {
            return val > 1;
      }
}

void testFunctor1()
{
      vector<int> vt;
      for(int i = 0; i < 15; i ++)
      {
             vt.push_back(i);
      }

    //现在我们可以把上面的一元谓词作为参数使用
    // 参数GreaterThanOne()是GreaterThanOne类的匿名对象
    //因为它里面重载了operator(), 所以我们又叫它为仿函数或者函数对象
    vector<int>::iterator it = find_if(vt.begin(),vt.end(),GreaterThanOne());  // 这句话也可以写成 auto it = find_if(vt.begin(),vt.end(),GreaterThanOne())
if(it == v.end())
{
cout << "Not Found" <<end1;
}
else
{
cout << "Found" << *it <<end1;
} }
int main()
{
   testFunctor1();
return 0;
}
复制代码

 上面的例子中,有用到一个std::find_if()函数的调用,我们正好趁这个机会来了解一下这个函数

std::find_if()函数功能: 按条件查找元素

函数原型
find_if(iterator begin, iterator end, _pred)
按值查找元素,找到的话就返回指定位置的迭代器,找不到就返回结束迭代器的位置
begin: 开始迭代器
end: 结束迭代器
_pred: 函数或者谓词 (返回bool类型的仿函数-谓词)

 

二元谓词

除了一元谓词外,还有二元谓词,顾名思义,二元谓词就是有2个参数返回值为bool类型的operator()

复制代码
#include <vector>
#include <algorithm>

//二元谓词例子
class CompareTwoValue
{
   public:
     bool operator(int x, int y)
     {
        return x > y;
     }
}

void testFunctor2()
{
      vector<int> vec;
      vec.push_back(100);
      vec.push_back(200);
      vec.push_back(300);
      vec.push_back(400);
      vec_push_back(500);

      
       //默认从小到大排序
       sort(vec.begin(),vec.end());
       for(vector<int>::iterator it = vec.begin(); it != vec.end() it++)
       {
              cout << *it << " ";
       }           
       cout << end1;

     //使用函数对象(仿函数)改变算法,使sort方法从大到小排序
     sort(vec.begin(),vec.end(),CompareTwoValue());
       for(vector<int>::iterator it = vec.begin(); it != vec.end() it++)
       {
              cout << *it << " ";
       }           
       cout << end1;
}

int main()
{
    testFunctor2();
    return 0;
}
复制代码

 

最后,我们大概来看一看仿函数在STL中的其他应用

STL中的内建函数对象 (仿函数)

要使用STL中的内建仿函数,需要包括头文件

#include <functional>  => 它里面包括的仿函数如下

算术仿函数

仿函数原型

template<class T> T plus<T>    //加法仿函数
template<class T> T minus<T>  //减法仿函数
template<class T> T multiplies<T>  //乘法仿函数
template<class T> T divides<T>   //除法仿函数
template<class T> T modulus<T>  //取模仿函数
template<class T> T negate<T> //取反仿函数

关系仿函数

template<class T> bool equal_to<T>    //等于
template<class T> bool not_equal_to<T>  //不等于
template<class T> bool greater<T>   //大于
template<class T> bool greater_equal<T>   //大于等于
template<class T> bool less<T>   //小于
template<class T> bool less_equal<T>  //小于等于

逻辑仿函数

template<class T> bool logical_and<T>   //逻辑与
template<class T> bool logical_or<T>   //逻辑或
template<class T> bool logical_not<T>    //逻辑非

 

posted on   新西兰程序员  阅读(39)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示