zoukankan      html  css  js  c++  java
  • 函数对象

      如果f是一个function object,则可以将operator()作用于f身上。他是一个行为类似于函数的对象,为了能够行为类似函数,其类别中必须定义(或重载、重写)function call运算符(operator()),就可以在函数对象后加一对小括号以此来调用函数对象定义的operator()。

      调用函数对象时构造函数和operator()执行顺序

    1. 首先执行构造函数,构造出一个匿名对象
    2. 然后在执行operator(),产生函数行为
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <string.h>
    #include <iterator>
    using namespace std;
    
    class F1
    {
        public:
            F1(string t):s1(t)
            {
                cout<<" 带参构造函数"<<endl;
            }
            F1()
            {
                cout<<" 无参构造函数"<<endl;
            }
            bool operator()(string s)
            {
                cout<<" operator()函数"<<endl;
                return strcmp(s.c_str(),s1.c_str());
            }
        private:
            string s1;
    };
    int main()
    {
        vector<string> vs{"hello"," ","word","!","how"," ","you","."};
        //1.F1 f1("you");被解析为f1.operator(arg);
        F1 f1("you");
        remove_copy_if(vs.begin(),vs.end(),ostream_iterator<string>(cout,"
    "),f1);
        cout<<"****************************************"<<endl;
        //2.
        remove_copy_if(vs.begin(),vs.end(),ostream_iterator<string>(cout,"
    "),F1("you"));
        cout<<"****************************************"<<endl;
        //3.
        F1()("hello");//这是一个函数调用的行为 
        return 0;
    }

      函数对象可以有自己的状态,也可以与函数配接器搭配使用。

    template<typename T, T add>
    struct m_plus
    {
        m_plus() { _add = add; }
        T operator()(const T& x) { return x + _add; }
        // 仿函数可以具有自己的状态
        int _add;
    };

      为了能够拥有配接能力,每一个仿函数必须定义自己的响应型别。这些型别是为了让配接器能够取出,获得仿函数的某些信息。

    unary_function

      来反应一元仿函数的参数型别和返回值型别。

    //一元仿函数
    template <class Arg,class Result>
    struct unary_function{
        typedef Arg argument_type;
        typedef Result result_type;
    };

    binary_function

      来反应二元仿函数的第一参数型别第二参数型别返回值型别。

    //二元仿函数
    template <class Arg1,class Arg2,Class Result>
    struct binary_function{
        typedef Arg1 firs_argument_type;
        typedef Arg2 second_argument_type;
        typedef Result result_type;
    };

    算数类仿函数

    template <class T>
    struct plus:public binary_function<T,T,T>{
        T operator()(const T & x,const T & y) const {return x + y;}
    };
    
    template <class T>
    struct minus:public binary_function<T,T,T>{
        T operator()(const T & x,const T & y) const {return x - y;}
    };
    
    tmeplate<class T>
    struct muliplies:public binary_function<T,T,T>{
        T operator()(const T & x,const T & y) const {return x * y;}
    };
    
    tmeplate<class T>
    struct divides:public binary_function<T,T,T>{
        T operator()(const T & x,const T & y) const {return x / y;}
    };
    
    tmeplate<class T>
    struct modulus:public binary_function<T,T,T>{
        T operator()(const T & x,const T & y) const {return x % y;}
    };
    
    tmeplate<class T>
    struct negate:public unary_function<T,T>{
        T operator()(const T & x) const {return -x;}
    };

    证同元素

      意思是数值A若与该元素做op运算,会得到A自己。例如加法的证同元素是0,任何元素加上0都是自己本身。乘法的证同元素是1,任何元素乘1都为元素本身。

    template<class T>
    inline T identity_element(plus<T>)
    {return T(0);}
    
    template<class T>
    inline T identity_element(multiplies<T>)
    {return T(1);}

    逻辑运算符仿函数

      他们都继承与二元仿函数。

    template<class T>
    struct logical_and:public binary_function<T,T,bool>{
        bool operator()(const T & x,const T & y) const {return x&&y;}
    };
    
    template<class T>
    struct logical_or:public binary_function<T,T,bool>{
        bool operator()(const T & x,const T & y) const {return x||y;}
    };
    
    template<class T>
    struct logical_not:public unary_function<T,bool>{
        bool operator()(const T & x) const {return !x;}
    };

    证同(identity)、选择(select)、投射(project)

    //证同函数。任何数值通过此函数后,不会有任何改变
    //此式运用于<stl_set.h>,用来指定RB-tree所需的KeyOfValue op
    //set元素键值即实值,所以采用identity
    template <class T>
    struct identity : public unary_function<T,T>{
        const T& operator()const T& x) const { return x; }
    };
    
    //选择函数:接收一个pair,返回其第一元素
    //此式运用于<stl_map.h>,用来指定RB-tree所需的KeyOfValue op
    //由于map系以pair元素的第一元素为其键值,所以采用select1st
    template <class Pair>
    struct select1st : public unary_function<Pair,typename Pair::first_type>
    {
        const typename Pair::first::first_type& operator()(const Pair& x)const{
            return x.first;
      }
    };
    
    //选择函数:接收一个Pair,传回其第二元素
    //SGI STL未运用此式
    template <class Pair>
    struct select2nd : public unary_function<Pair,typename Pair::second_type>
    {
        const typename Pair::first::second_type& operator()(const Pair& x)const{
            return x.second;
      }
    };
    
    //投射函数:传回第一参数,忽略第二参数
    //SGI STL未运用此式
    template<class Arg1,class Arg2>
    struct project1st : public binary_function<Arg1,Arg2,Arg1>{
        Arg1 operator()(const Arg1& x,const Arg2&)const{ return x; }
    };
    
    //投射函数:传回第二参数,忽略第一参数
    //SGI STL未运用此式
    template<class Arg1,class Arg2>
    struct project2nd : public binary_function<Arg1,Arg2,Arg2>{
        Arg1 operator()(const Arg1&,const Arg2& y)const{ return y; }
    };
  • 相关阅读:
    CF431E Chemistry Experiment
    BZOJ 4173: 数学
    BZOJ 2426: [HAOI2010]工厂选址
    BZOJ 2580: [Usaco2012 Jan]Video Game
    BZOJ 4237: 稻草人
    BZOJ 2434: [Noi2011]阿狸的打字机
    BZOJ 3881: [Coci2015]Divljak
    BZOJ 2754: [SCOI2012]喵星球上的点名
    BZOJ 1009: [HNOI2008]GT考试
    BZOJ 3731: Gty的超级妹子树
  • 原文地址:https://www.cnblogs.com/tianzeng/p/8711758.html
Copyright © 2011-2022 走看看