• 【C++】仿函数


    25 仿函数

    就是重载了()操作符的类,就是用于需要函数作为参数的函数

    25.1 格式

    class Linear
    {
        private:
        double slope;
        double y0;
        public:
        Linear(double sl_ = 1, double y_ = 0): slope(sl_), y0(y_) {}
        double operator()(double x) {return y0 + slope * x; }
    };

    25.2 仿函数概念

    1.一个generator(生成器)可以是一个没有参数的仿函数 ​ 2.带有一个参数的仿函数叫做unary function(一元函数) ​ 3.带有两个参数的仿函数叫做binary function(二元函数)

    25.3 仿函数概念改进

    1.返回一个bool值的unary function叫做predicate(谓词) ​ 2.返回一个bool值的binary function叫做binary predicate(二元谓词)

    25.4 仿函数举例

    template
    Function for_each(InputIterator first, InputIterator last, Function f);
    void ShowReview(const Review &);

    list.remove_if(func)---对list中的每个元素都执行func;如果func返回true,则删除list中对应的元素,如果func返回false,则保留list中对应的元素。

    25.5 预定义的仿函数

    定义的头文件:functional 操作符和伪函数等效

    OperatorFunctor Equivalent
    +plus
    -minus
    *multiplies
    /divides
    %modulus
    -negate
    ==equal_to
    !=not_equal_to
    >greater
    <less
    >=greater_equal
    <=less_equal
    &&logical_and
    ||logical_or
    !logical_not

    举例:transform()的两个版本

    transform(gr8.begin(), gr8.end(), out, sqrt);
    //第一、二个参数是一个迭代器范围,第三个参数是指定复制结果位置的迭代器,第四个参数是应用于范围中每个元素的仿函数。
    transform(gr8.begin(), gr8.end(), m8.begin(), out, mean);
    //第一、二个参数是一个迭代器范围,第三个参数指向第二个范围的开头,第四个参数是指定复制结果位置的迭代器,第五个参数是应用于范围中每个元素的仿函数。

    25.6 可适应的仿函数和函数适配器

    上面的所有预定义的仿函数都是适配器。

    25.6.1五种适配器

    adaptable generators, adaptable unary functions, adaptable binary functions,adaptable predicates, adaptable binary predicates

    25.6.2 解决的问题

    在将可使用的仿函数(必须是可适应的)作为参数传递时,如果该函数有两个形参,但是将该函数作为参数的函数只能提供一个参数,这种情况该如何处理? 此时需要一个函数适配器将 可适应的二元仿函数 转换为可适应的一元仿函数。

    25.6.3 binder1st和binder2nd类

    STL提供了binder1st和binder2nd类,它可以将可适应的二元函数转换为可适应的一元函数

    binder1st(f2, val) f1;
    f1(x);//等价于f2(val,x);
    //bind1st函数
    bind1st(multiplies(), 2.5)//返回一个binder1st对象

    举例:要给列表中的每个元素都乘以2.5.

    25.7 举例

    代码

    /*
    Project name :          __26Function_Objects
    Last modified Date:     2022年4月11日17点09分
    Last Version:           V1.0
    Descriptions:           仿函数
    */           
    /*
    仿函数:就是重载了()操作符的类,就是用于需要函数作为参数的函数
        格式:
            class Linear
            {
            private:
                double slope;
                double y0;
            public:
                Linear(double sl_ = 1, double y_ = 0): slope(sl_), y0(y_) {}
                double operator()(double x) {return y0 + slope * x; }
            };
    仿函数概念:
        1.一个generator(生成器)可以是一个没有参数的仿函数
        2.带有一个参数的仿函数叫做unary function(一元函数)
        3.带有两个参数的仿函数叫做binary function(二元函数)
    仿函数概念改进:
        1.返回一个bool值的unary function叫做predicate(谓词)
        2.返回一个bool值的binary function叫做binary predicate(二元谓词)
    仿函数举例:
        template
        Function for_each(InputIterator first, InputIterator last, Function f);
        void ShowReview(const Review &);
    ​
        list.remove_if(func)---对list中的每个元素都执行func;如果func返回true,则删除list中对应的元素,如果func返回false,则保留list中对应的元素。
    预定义的仿函数:
        定义的头文件:functional
        操作符和伪函数等效:
            Operator        Functor Equivalent
            +               plus
            -               minus
            *               multiplies
            /               divides
            %               modulus
            -               negate
            ==              equal_to
            !=              not_equal_to
            >               greater
            <               less
            >=              greater_equal
            <=              less_equal
            &&              logical_and
            ||              logical_or
            !               logical_not
        举例:transform()的两个版本
            transform(gr8.begin(), gr8.end(), out, sqrt);
            //第一、二个参数是一个迭代器范围,第三个参数是指定复制结果位置的迭代器,第四个参数是应用于范围中每个元素的伪函数。
            transform(gr8.begin(), gr8.end(), m8.begin(), out, mean);
            //第一、二个参数是一个迭代器范围,第三个参数指向第二个范围的开头,第四个参数是指定复制结果位置的迭代器,第五个参数是应用于范围中每个元素的伪函数。
    可适应的仿函数和函数适配器
        上面的所有预定义的仿函数都是适配器。
        有五种适配器:
            adaptable generators, adaptable unary functions, adaptable binary functions,
            adaptable predicates, adaptable binary predicates
        解决的问题:
            在将可使用的仿函数(必须是可适应的)作为参数传递时,如果该函数有两个形参,但是将该函数作为参数的函数只能提供一个参数,这种情况该如何处理?
            此时需要一个函数适配器将 可适应的二元仿函数 转换为可适应的一元仿函数。
        binder1st和binder2nd类
            STL提供了binder1st和binder2nd类,它可以将可适应的二元函数转换为可适应的一元函数
            binder1st(f2, val) f1;
            f1(x);//等价于f2(val,x);
            //bind1st函数
            bind1st(multiplies(), 2.5)//返回一个binder1st对象
        举例:要给列表中的每个元素都乘以2.5.
            
    */
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    /*
    TooBig也可以是这个格式:
    首先定义函数:
    template 
    bool tooBig(const T & val, const T & lim)
    {
        return val > lim;
    }
    然后定义仿函数类使用上述函数:
    template
    class TooBig2
    {
        private:
            T cutoff;
        public:
            TooBig2(const T & t) : cutoff(t) {}
            bool operator()(const T & v) { return tooBig(v, cutoff); }
    };
    ​
    */
    template // functor class defines operator()()
    class TooBig
    {
    private:
        T cutoff;
    public:
        TooBig(const T& t) : cutoff(t) {}
        bool operator()(const T& v) { return v > cutoff; }
    };
    void outint(int n) { std::cout << n << " "; }
    void Show(double);
    const int LIM = 6;
    int main()
    {
        using namespace std;
        TooBig f100(100); // limit = 100
        int vals[10] = { 50, 100, 90, 180, 60, 210, 415, 88, 188, 201 };
        list yadayada(vals, vals + 10); // range constructor
        list etcetera(vals, vals + 10);
        // C++11 can use the following instead,下面这个是初始化列表
        // list yadayada = {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};
        // list etcetera {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};
        cout << "functor*********************************************************" << endl;
        cout << "Original lists:\n";
        for_each(yadayada.begin(), yadayada.end(), outint);
        cout << endl;
        for_each(etcetera.begin(), etcetera.end(), outint);
        cout << endl;
        yadayada.remove_if(f100); // use a named function object
        etcetera.remove_if(TooBig(200)); // construct a function object
        cout << "Trimmed lists:\n";
        for_each(yadayada.begin(), yadayada.end(), outint);
        cout << endl;
        for_each(etcetera.begin(), etcetera.end(), outint);
        cout << endl;
        cout << "Adaptable Functors and Function Adapters**************************" << endl;
        double arr1[LIM] = { 28, 29, 30, 35, 38, 59 };
        double arr2[LIM] = { 63, 65, 69, 75, 80, 99 };
        vector gr8(arr1, arr1 + LIM);
        vector m8(arr2, arr2 + LIM);
        cout.setf(ios_base::fixed);
        cout.precision(1);
        cout << "gr8:\t";
        for_each(gr8.begin(), gr8.end(), Show);
        cout << endl;
        cout << "m8: \t";
        for_each(m8.begin(), m8.end(), Show);
        cout << endl;
        vector sum(LIM);
        transform(gr8.begin(), gr8.end(), m8.begin(), sum.begin(),
            plus());
        cout << "sum:\t";
        for_each(sum.begin(), sum.end(), Show);
        cout << endl;
        vector prod(LIM);
        transform(gr8.begin(), gr8.end(), prod.begin(),
            bind1st(multiplies(), 2.5));
        cout << "prod:\t";
        for_each(prod.begin(), prod.end(), Show);
        cout << endl;
    ​
        return 0;
    }
    ​
    void Show(double v)
    {
        std::cout.width(6);
        std::cout << v << ' ';
    }

    运行结果:

    functor*********************************************************
    Original lists:
    50 100 90 180 60 210 415 88 188 201
    50 100 90 180 60 210 415 88 188 201
    Trimmed lists:
    50 100 90 60 88
    50 100 90 180 60 88 188
    Adaptable Functors and Function Adapters**************************
    gr8:      28.0   29.0   30.0   35.0   38.0   59.0
    m8:       63.0   65.0   69.0   75.0   80.0   99.0
    sum:      91.0   94.0   99.0  110.0  118.0  158.0
    prod:     70.0   72.5   75.0   87.5   95.0  147.5
    ​
    D:\Prj\_C++Self\_24Function_Objects\Debug\_24Function_Objects.exe (进程 12252)已退出,代码为 0。
    要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
    按任意键关闭此窗口. . .
  • 相关阅读:
    安装配置 hbase
    水仙花数-C语言和python实现
    山东大学软件学院深度学习期末回忆版
    ZZULIOJ 1105: 判断友好数对(函数专题) (C/C++)
    git
    C语言:数组名和数组地址
    Linux下 生成coredump文件
    VSCode中使用github
    linux 性能分析工具perf
    当我开始刻意不工作
  • 原文地址:https://blog.csdn.net/weixin_44410704/article/details/128038327