美文网首页
六、函数对象、谓词概念、内建函数对象

六、函数对象、谓词概念、内建函数对象

作者: 木鱼_cc | 来源:发表于2018-06-30 20:10 被阅读0次

    1.函数对象的概念

    重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象,也叫仿函数(functor),其实就是重载"()"操作符,使得类对象可以像函数那样调用

    注意:

    • 函数对象(仿函数)是一个类,不是一个函数
    • 函数对象(仿函数)重载了"()"操作符使得它可以像函数一样调用
    #include <iostream>
    #include <vector>
    #include <string>
    using namespace std;
    
    void print(int index){
       cout<<"hello world..."<<index<<endl;
    }
    
    class myprint{
    public:
        void operator()(int index){
            cout<<"hello world"<<index<<endl;
        }
    }
    
    
    //函数对象和普通函数对比
    void test01(){
     
       print(10);
       myprint myp;
       myp(10);//效果一样!
    }
    
    //函数对象超出了普通函数的概念,可以保存函数调用状态
    //统计函数调用次数?
    int g_count = 0;
    void print03(){
        g_count++;
    }
    
    class myprint03{
        myprint03():count(0){}
        void operator()(){
         count++;
        } 
        int count;
    }
    
    void test3(){
       print03();
       print03();
    
       cout<<g_count<<endl;//输出2
    
       myprint03 myp03;
       myp03();
       myp03();
       myp03();
       cout<< myp03().count<<endl;//输出3
    }
    
    //函数对象做参数,做返回值
    class myprint04{
    public:
        myprint04():count(0){};
        void operator()(int v){
           cout<<v<<" ";
           cout<<"hello world"<<endl;
           count++;
        }
        int count;
    }
    
    
    void test4(){
        vector<int> v;
        for(int i = 0 ; i < 10;i++){
            v.push_back(i);
        }
    
    /*_Fn1是函数对象!!!!
    template<class _InIt,class _Fn1> inline
    _Fn1 for_each(_InIt _First,_InIt _Last,_Fn1 _Func)
    {   //perform function for each element
        _DEBUG_RANGE(_First,_Last);
        _DEBUG_POINTER(_Func);
        _For_each(_Unchecked(_First),Unchecked(_Last),_Func);
    
        return (_STD move(_Func));
    }
    
    template<class _InIt,class _Fn1>inline
    void _For_each(_InIt _First,_InIt _Last,_Fn1& _Func)
    {   //perform function for each element
       for(;_First != _Last;++_First)_Func(*_First);//函数对象
    }
    
    */
        myprint04 myp04;
        for_each(v.begin(),v.end(),myp04);//函数对象作参数//打印出来了 1 2 3 ....
        cout<<"count:"<<myp04.count<<endl;//发现是0!!明明可以打印hello world
        //原因是它传参过程中拷贝成了另一份,返回来了你没有接受!
    
        //所以应该还是
        myprint04 myp05 = for_each(v.begin(),v.end(),myp04);
        cout<<"count:"<<myp04.count<<endl;//0
        cout<<"count:"<<myp05.count<<endl;//10
    }
    int main(){
      // test3();
       test4();
       return 0;
    }
    

    2.谓词概念

    谓词是指普通函数重载的operator()返回值是bool类型的函数对象(仿函数)。如果operator接受一个参数,那么就叫做一元谓词,如果接受两个参数,那么就叫做二元谓词。谓词可作为一个判断式

    一元函数对象 应用举例:for_each
    一元谓词 应用举例:find_if
    二元函数对象 应用举例:transform
    二元谓词 应用举例 sort

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    //如果你写的函数对象接受一个参数,那么就叫做 一元函数对象
    //如果你写的函数对象接受两个参数,那么就叫做 二元函数对象
    
    //如果你写的函数对象或者普通函数接受一个参数,并且返回值是BOOL ,叫一元谓词
    //如果你写的函数对象或者普通函数接受两个参数,并且返回值是BOOL ,叫二元谓词
    
    
    //一元函数对象 应用举例:for_each
    class print{
    public:
        void operator()(int v){
          cout<<v<<" ";
        }
    }
    
    void print2(int v){
        cout<<v<<" ";
    }
    
    void test01(){
        vector<int> v;
        for(int i = 0;i<10;i++){
            v.push_back(i);
        }
        //print p;
        for_each(v.begin(),v.end(),print());//函数对象
        for_each(v.begin(),v.end(),print2);//普通函数
    }
    
    
    //一元谓词    应用举例:find_if    找到规则对比下的首元素
    class mycompare{
    public:
        bool operator()(int v){
           if (v > 7)return true;
           else return false;
        }
    }
    void test02(){
        vector<int> v;
        for(int i = 0;i<10;i++){
            v.push_back(i);
        }
    
        /*
        _Pr是bool类型别名
        template<class _InIt,class _Pr> inline
         _InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred)
        {   // find first satisfying _Pred
        _DEBUG_RANGE(_First, _Last);
        _DEBUG_POINTER(_Pred);
        return (_Rechecked(_First,
             _Find_if(_Unchecked(_First),_Unchecked(_Last),Pred)));
        }
        
        template<class _InIt,class _Pr> inline
        _InIt _Find_if(_InIt _First,InIt _Last,_Pr _Pred)
        {  // find first satisfying _Pred
        for(;_First != _Last;++_First)
           if(_Pred(*_First))
              break;
        return (_First);
        }
        */
    
        vector<int>::itertaor pos = find_if(v.begin(),v.end(),mycompare());//匿名函数对象
        if (pos == v.end())
        {
            cout<<"没找到"<<endl;
        }
        else{
            cout<<"找到了"<<*pos<<endl;//8
        }
    }
    
    
    //二元函数对象 应用举例:transform    对两个容器进行等位操作,完成后返回给第三个容器
    class myplus{
    public:
       int operator()(int v1,int v2){//v1是第一个容器中的元素 v2是第二个容器中的元素
          return v1 + v2;
       }
    }
    
    
    void test03(){
        vector<int> v1,v2,v3;
        for(int i = 0;i<10;i++){
            v1.push_back(i);
            v2.push_back(i+1);
        }
    
        /*
    
        template<class _InIt1,
            class _InIt2,
            class _OutIt,
            class _Fn2> inline
            _OutIt transform(_InIt1 _First1,_InIt1 _Last1,
                _InIt2 _First2, _OutIt _Dest, _Fn2 _Func)
        {   // transform [_First1, _Last1) and [_First2, ...) with _Func
        _DEBUG_POINTER(_Dest);
        _DEBUG_POINTER(_Func);
        _DEBUG_RANGE(_First1, _Last1);
        for(_First != _Last1)
           return (_Transform2(_Unchecked(_First1),_Unchecked(_Last1),
               _First2, _Dest, _Func,
               _Is_checked(_Dest)));
    
        return (_Dest);
        }
    
        template<class _InIt1,
            class _InIt2,
            class _OutIt,
            class _Fn2> inline
            _OutIt _Transform(_InIt1 _First1, _InIt1 _Last1,
            _InIt2 _First2, _OutIt _Dest, _Fn2 _Func)
            {   // transform [_First1, _Last1) and [_First2, ...) with _Func
            for (; _First1 != _Last1; ++_First1, ++_First2, ++_Dest)
            *_Dest = _Func(*_First1, *_First2);
            return (_Dest);
            }
        
        */
        //v3最初没有开辟内存,会挂掉
        v3.resize(v1.size());
    
        //for_each借来打印一下
        for_each(v1.begin(),v1.end(),print2);
        cout<<endl;
        for_each(v2.begin(),v2.end(),print2);
        cout<<endl;
        for_each(v3.begin(),v3.end(),print2);
        cout<<endl;
    
    
        transform(v1.begin(),v1.end(),v2.begin(),v3.begin(),myplus());//结果放到v3容器中了
        cout<<endl;
       
        for_each(v1.begin(),v1.end(),print2);
        cout<<endl;
        for_each(v2.begin(),v2.end(),print2);
        cout<<endl;
        for_each(v3.begin(),v3.end(),print2);
        cout<<endl;
    }
    
    //二元谓词 应用举例 sort
    class mycompare04{
    public:
        bool operator()(int v1,int v2){
            return v1 > v2;//从大到小
        }
    }
    void test04(){
    
       vector<int> v;
       v.push_back(5);
       v.push_back(2);
       v.push_back(7);
       v.push_back(9);
    
       /*
       template<class _RanIt,
        class _Pr> inline
        void sort(_RanIt _First, _RanIt _Last, _Pr _Pred)
        {   // order [_First, _Last), using _Pred
        _DEBUG_RANGE(_First, _Last);
        _DEBUG_POINTER(_Pred);
        _Sort(_Unchecked(_First), _Unchecked(_Last), _Last - _First, _Pred);
        }
    
       */
       for_each(v.begin(),v.end(),print2);
       cout<<endl;
       sort(v.begin(),v.end(),mycompare04());
       cout<<endl;
       for_each(v.begin(),v.end(),print2);
       cout<<endl;
    
    
    }
    
    int main(){
    
       test01();
       test02();
       test03();
       test04();
       return 0;
    }
    

    3.内建函数对象

    STL内建了一些函数对象。分为:算数类函数对象,关系运算类函数对象,逻辑运算类仿函数。这些方函数所产生的对象,用法和一般函数完全相同,当然我们还可以产生无名的临时对象来履行函数功能。使其内建函数对象,需要引入头文件#include <functional>

    • 6个算数类函数对象,除了negate是一元运算,其他都是二元运算
    template<class T> T plus<T> //加法仿函数
    template<class T> T minute<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> //取反仿函数
    
    • 6个关系运算类函数对象,每一种都是二元运算
    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> //小于等于
    
    • 逻辑运算类运算函数,not为一元运算,其余为二元运算
    template<class T> bool logical_and<T> //逻辑与
    template<class T> bool logical_or<T> //逻辑或
    template<class T> bool logical_not<T> //逻辑非
    

    例子

    #include <iostream>
    #include <functional>
    #include <string>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    
    void test01(){
        plus<int> myplus;//函数对象
        int ret = myplus(10,20);
        cout<<ret<<endl;//30
    
        plus<string> myplus2;
        string s1 = "aaa";
        string s2 = "bbb";
        string ret2 = myplus2(s1,s2);
        cout<<ret2<<endl;//aaabbb
    
        cout<<plus<int>()(10,20)<<endl;//匿名函数对象  30
    }
    
    //transform
    void print(int v){
        cout<<v<<" ";
    }
    void test02(){
        vector<int> v1,v2,v3;
        for(int i = 0; i < 10;i++){
            v1.push_back(i);
            v2.push_back(i+1);
    
        }
    
        v3.resize(v1.size());
        transform(v1.begin(),v1.end(),v2.begin(),v3.begin(),plus<int>());//用预定义的函数对象!!!
        cout<<endl;
        for_each(v3.begin(),v3.end(),print);
        cout<<endl;
    }
    
    
    int main(){
    
      
       return 0;
    }
    

    相关文章

      网友评论

          本文标题:六、函数对象、谓词概念、内建函数对象

          本文链接:https://www.haomeiwen.com/subject/fewayftx.html