C++ STL/ (11) 函数对象

我们在介绍容器set的时候就涉及到了函数对象这个概念,本节就是在原来的基础之上,系统深入的谈一谈STL中的函数对象。


  • 函数对象的基本概念

    • 函数对象本质上是一个类而不是一个函数
    • 函数对象重载了运算符(),从而使对象能够像函数一样的被调用
  • 函数对象与普通函数的对比

    • 函数对象超出了普通函数的功能,能够保存函数调用状态(如果使用全局变量保存函数调用次数,要给程序加锁,解锁。所以不推荐使用全局变量;而函数对象则能够很好的解决该问题。)

      
      #include <iostream>
      
      
      using namespace std;
      
      class compare{
      public:
          int cnt = 0;    //可以记录函数调用次数
          bool operator()(int i, int j){
              this->cnt++;
              return i > j;
          }
      };
      bool compare_fun(int i, int j){
          return i > j;
      }
      int main(){
          compare a, b;
          cout<<a(1, 2)<<" "<<compare_fun(1,2)<<endl;
          cout << b(4, 3) << " " << compare_fun(2, 1) << endl;
          a(3, 4);
          a(5, 6);
          a(7, 8);
          cout << "函数对象a调用次数: " << a.cnt << " " << "函数对象b调用次数: " <<b.cnt << endl;
      
      
          return 0;
      }
    • 函数对象可以做参数,做返回值
      利用for_each实现打印容器vector中的所有元素

      
      #include <iostream>
      
      
      #include <vector>
      
      
      #include <algorithm>
      
      
      using namespace std;
      
      
      
      class print{
      public:
          int cnt = 0;
          void operator()(int i){
              cout << i << " ";
              cnt++;
          }
      };
      
      int main(){
          vector<int> v;
          for (int i = 0; i < 10; i++){
              v.push_back(i); 
          }
          print p1;
          p1=for_each(v.begin(), v.end(), p1); //函数对象做函数参数和函数返回值,这是普通函数无法实现的
          cout << endl;
          cout << p1.cnt << endl;
      
          return 0;
      }

  • STL中预定义的函数对象
    STL中的函数对象都封装在functional头文件中。

    下面以plus为例子,讲解一下STL封装的函数对象如何使用。

    
    #include <iostream>
    
    
    #include <vector>
    
    
    #include <string>
    
    
    #include <functional>
    
    
    #include <algorithm>
    
    
    using namespace std;
    int main(){
        plus<int> plus_int;
        int ret = plus_int(10, 20);
        cout << ret << endl;
    
        plus<string> plus_str;
        string a = "aaa";
        string b = "bbb";
        string c = plus_str(a, b);
        cout << c << endl;
    
        cout << plus<int>()(1, 2) << endl;  //匿名对象
    
        return 0;
    }

  • 一元函数对象,二元函数对象,一元谓词,二元谓词
    函数对象接收一个参数,称为一元函数对象;函数对象接收两个参数,则称为二元函数对象。
    函数对象或者普通函数接收一个参数,并且返回值是bool数据类型,称为一元谓词;函数对象或者普通函数接收两个参数,并且返回值是bool数据类型,则称为二元谓词。
    我们下面以for_each(),find_if(),transform()和sort为例子,分别讲解一元函数对象,一元谓词,二元函数对象,二元谓词。

    
    #include <iostream>
    
    
    #include <vector>
    
    
    #include <string>
    
    
    #include <functional>
    
    
    #include <algorithm>
    
    
    using namespace std;
    
    template<class T>
    class print{
    public:
        int ret = 0;
        void operator()(T i){
            cout << i << " ";
            ret++;
        }
    };
    
    class compare{
    public:
        bool operator()(int i){
            return i > 7;
        }
    };
    
    class sort_int{
    public:
        bool operator()(int v1, int v2){
            return v1 > v2;
        }
    };
    
    void test01(){
        //一元函数对象 for_each
        vector<int> v;
        for (int i = 0; i < 100; i++){
            v.push_back(i + 1);
        }
        print<int> print_int;
        print_int = for_each(v.begin(), v.end(), print_int);
        cout << endl;
        cout << print_int.ret << endl;
    
    }
    
    void test02(){
        //一元谓词  find_if
        vector<int> v;
        v.push_back(1);
        v.push_back(7);
        v.push_back(8);
        vector<int>::iterator i = find_if(v.begin(), v.end(), compare());
        if (i == v.end()){
            cout << "cannot find!!!" << endl;
        }
        else{
            cout << "find : " << *i << endl;
        }
    
    }
    
    void test03(){
        //transform() 对两个容器进行操作,将结果存放在第三个容器中
        vector<int> v1,v2,v3;
        for (int i = 0; i < 10; i++){
            v1.push_back(i);
            v2.push_back(i + 1);
        }
    
        //v3在transform之前要先开辟内存空间
        v3.resize(100);
    
        transform(v1.begin(),v1.end(),v2.begin(),v3.begin(),plus<int>());
    
        for (int i = 0; i < v3.size(); i++){
            cout << v3.at(i) << " ";
        }
        cout << endl;
    }
    void test04(){
        //二元谓词 sort
        vector<int> v1;
        v1.push_back(3);
        v1.push_back(2);
        v1.push_back(9);
        v1.push_back(6);
        for_each(v1.begin(), v1.end(), print<int>());
        cout << endl;
        sort(v1.begin(), v1.end(), sort_int());
        for_each(v1.begin(), v1.end(), print<int>()); cout << endl;
    
    }
    
    int main(){
        test01();
        test02();
        test03();
        test04();
        return 0;
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值