对于仿函数的记录

一,概述
        仿函数(functor),就是使一个类的使用看上去象一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。
  有些功能的的代码,会在不同的成员函数中用到,想复用这些代码。

                            1)公共的函数,可以,这是一个解决方法,不过函数用到的一些变量,就可能成为公共的全局变量,再说为了复用这么一片代码,就要单立出一个函数,也不是很好维护。

                            2)仿函数,写一个简单类,除了那些维护一个类的成员函数外,就只是实现一个operator(),在类实例化时,就将要用的,非参数的元素传入类中。


二,仿函数(functor)在各编程语言中的应用

  1)C语言使用函数指针回调函数来实现仿函数,例如一个用来排序的函数可以这样使用仿函数
  

[html]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. //int sort_function( const void *a, const void *b);  
  4. int sort_function( const void *a, const void *b)  
  5. {     
  6.     return *(int*)a-*(int*)b;  
  7. }  
  8.   
  9. int main()  
  10. {  
  11.      
  12.    int list[5] = { 54, 21, 11, 67, 22 };  
  13.    qsort((void *)list, 5, sizeof(list[0]), sort_function);//起始地址,个数,元素大小,回调函数   
  14.    int  x;  
  15.    for (x = 0; x < 5; x++)  
  16.           printf("%i\n", list[x]);  
  17.                     
  18.    return 0;  
  19. }  

        2)在C++里,我们通过在一个类中重载括号运算符的方法使用一个函数对象而不是一个普通函数。

[html]  view plain  copy
  1. #include <iostream>  
  2. #include <algorithm>  
  3.   
  4. using namespace std;  
  5. template<typename T>  
  6. class display  
  7. {  
  8. public:  
  9.     void operator()(const T &x)  
  10.     {  
  11.         cout<<x<<" ";   
  12.     }   
  13. };   
  14.   
  15.   
  16. int main()  
  17. {  
  18.     int ia[]={1,2,3,4,5};  
  19.     for_each(ia,ia+5,display<int>());   
  20.       
  21.     return 0;   
  22. }   


三,仿函数在STL中的定义

        要使用STL内建的仿函数,必须包含<functional>头文件。而头文件中包含的仿函数分类包括

         1)算术类仿函数

               加:plus<T>

               减:minus<T>

               乘:multiplies<T>

               除:divides<T>

               模取:modulus<T>

               否定:negate<T>

例子:

[html]  view plain  copy
  1. #include <iostream>  
  2. #include <numeric>  
  3. #include <vector>   
  4. #include <functional>   
  5. using namespace std;  
  6.   
  7. int main()  
  8. {  
  9.     int ia[]={1,2,3,4,5};  
  10.     vector<int> iv(ia,ia+5);  
  11.     cout<<accumulate(iv.begin(),iv.end(),1,multiplies<int>())<<endl;   
  12.       
  13.     cout<<multiplies<int>()(3,5)<<endl;  
  14.       
  15.     modulus<int>  modulusObj;  
  16.     cout<<modulusObj(3,5)<<endl; // 3   
  17.     return 0;   
  18. }   


         2)关系运算类仿函数

               等于:equal_to<T>

               不等于:not_equal_to<T>

               大于:greater<T>

               大于等于:greater_equal<T>

               小于:less<T>

               小于等于:less_equal<T>

              从大到小排序:

[html]  view plain  copy
  1. #include <iostream>  
  2. #include <algorithm>  
  3. #include <vector>   
  4.   
  5. using namespace std;  
  6.   
  7. template <class T>   
  8. class display  
  9. {  
  10. public:  
  11.     void operator()(const T &x)  
  12.     {  
  13.         cout<<x<<" ";   
  14.     }   
  15. };  
  16.   
  17. int main()  
  18. {  
  19.     int ia[]={1,5,4,3,2};  
  20.     vector<int> iv(ia,ia+5);  
  21.     sort(iv.begin(),iv.end(),greater<int>());  
  22.     for_each(iv.begin(),iv.end(),display<int>());   
  23.     return 0;   
  24. }   

            3)逻辑运算仿函数

                 逻辑与:logical_and<T>

                 逻辑或:logical_or<T>

                 逻辑否:logical_no<T>


4:附录

class AA

{

public:

AA(int a)

:_a(a)

{

}


bool operator > (const AA & other) const

{

return _a > other._a;

}

public:

int _a;

};



int main(int argc, const char * argv[]) {

std::vector<AA> ve{6,7,2,4,8,1,0};

std::sort(ve.begin(), ve.end(), std::greater<AA>());

for (auto it : ve)

{

printf("%d   ", it._a);

}


}



<think>好的,我现在需要回答用户关于C++仿函数的定义和使用方法的问题。首先,我得回忆一下仿函数的基本概念。仿函数,也就是函数对象,是一个类,通过重载operator()运算符,使得其实例可以像函数一样被调用。这点我记得没错吧?根据用户提供的引用[1]和[2],仿函数确实是通过重载operator()来实现的,这样类的对象就可以像函数那样使用,比如在STL算法中作为回调函数。 接下来,用户可能想知道如何具体定义一个仿函数。我应该给出一个简单的例子,比如实现一个加法器。例如,定义一个Add类,里面有一个operator()接受两个参数,返回它们的和。然后演示如何创建这个类的实例,并调用它。这样用户能直观地看到仿函数的定义和使用方式。 然后,我需要说明仿函数的优势。比如,相对于普通函数,仿函数可以保存状态,这在多次调用时很有用。比如,可以有一个计数器记录被调用的次数。这需要举一个例子,比如Counter类,每次调用operator()时增加计数器,并输出当前计数。这样可以展示仿函数的状态保持能力,而普通函数做不到这一点。 另外,用户提到的引用[3]提到了Lambda表达式和仿函数的关系。可能这里需要简要比较两者的异同。比如,Lambda本质上是一个匿名函数对象,编译器会将其转换为类似仿函数的类。但仿函数因为是有名字的类,可能更适合需要重复使用或更复杂的情况。 然后,应用场景方面,用户可能想知道仿函数在STL中的使用。比如,在sort函数中,可以传递一个自定义的比较仿函数,来实现不同的排序方式。例如,使用GreaterThan仿函数来按特定条件排序,或者使用Transform仿函数在transform算法中进行转换操作。这些例子能帮助用户理解仿函数在实际编程中的用处。 最后,可能需要对比仿函数和函数指针、Lambda的优缺点。比如,仿函数可以内联,可能有更好的性能;而Lambda在C++11之后更简洁,但复杂逻辑可能还是用仿函数更清晰。这部分需要简明扼要,避免让用户感到困惑。 检查一下是否有遗漏的点。用户问题主要是定义和使用方法,所以需要覆盖定义步骤、示例代码、优势、应用场景。同时,要确保所有数学公式用$...$,独立公式用$$...$$,但当前问题可能不涉及数学公式,所以可能不需要特别处理。但如果有例子中的代码,需要用代码块包裹,比如用```cpp。 最后生成相关问题,可能需要包括仿函数的优缺点、与Lambda的比较、在STL中的具体应用例子等。确保问题与用户当前问题相关,帮助用户深入理解。</think>### C++仿函数(Functor)的定义与使用方法 #### 1. 仿函数的定义 仿函数(Functor)是一种**通过重载函数调用运算符`operator()`** 实现的类对象,使其可以像普通函数一样被调用[^2]。其核心特点是: - 语法表现类似函数调用 - 允许保存状态(普通函数无法实现) - 适用于模板编程和STL算法 #### 2. 基本实现示例 ```cpp // 定义加法仿函数 class Add { public: int operator()(int a, int b) const { return a + b; } }; // 使用示例 Add adder; int result = adder(3, 5); // 输出8 ``` #### 3. 仿函数的优势 **状态保持能力**是仿函数与普通函数的核心差异: ```cpp class Counter { private: int count = 0; public: void operator()() { std::cout << "调用次数:" << ++count << std::endl; } }; Counter counter; counter(); // 输出"调用次数:1" counter(); // 输出"调用次数:2" ``` #### 4. 在STL中的应用场景 仿函数广泛应用于标准模板库的算法中: 1. **排序条件控制**: ```cpp struct GreaterThan { bool operator()(int a, int b) const { return a > b; } }; std::vector<int> nums {5,2,4,1}; std::sort(nums.begin(), nums.end(), GreaterThan()); // 降序排列 ``` 2. **变换操作**: ```cpp class Square { public: int operator()(int x) const { return x * x; } }; std::transform(nums.begin(), nums.end(), nums.begin(), Square()); ``` #### 5. 与Lambda表达式对比 | 特性 | 仿函数 | Lambda表达式 | |--------------------|--------------------------|--------------------------| | 语法复杂度 | 需要显式定义类 | 匿名即时定义 | | 代码复用性 | 支持多场景复用 | 局限于定义位置 | | 状态管理 | 类成员变量 | 捕获列表 | | 模板参数兼容性 | 可直接作为模板参数 | 需`decltype`推导类型[^3] | #### 6. 高级应用:策略模式 仿函数可配合模板实现灵活的策略模式: ```cpp template<typename T, typename Comparator> class SortedContainer { Comparator comp; std::vector<T> data; public: void insert(T value) { // 使用comp比较器维护有序性 } }; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值