zoukankan      html  css  js  c++  java
  • C++ STL 之 函数对象适配器

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

    struct myfuncobj01
    {
      bool operator(int v){} // 接受一个参数,并且返回值为 Bool 即一元谓词
    }
    bool compare01(int v); // 同样是叫做一元谓词
    struct myfuncobj02
    {
      bool operator(int v1,int v2){} // 接受两个参数,返回值为 Bool 即二元谓词
    }
    bool compare02(int v1,int v2); // 同样是叫做二元谓词

    函数对象适配器是完成一些配接工作,这些配接包括绑定(bind),否定(negate),以及对一般函数或成员函数的修饰,使其成为函数对象。
    如果希望函数对象适配器能对我们自己编写的函数对象有效,我们需要根据我们的函数对象类型继承 STL 的父类对象。
    如果你本身是二元函数对象 需要继承
    二元函数继承:public binary_function<参数类型,参数类型,返回类型>
    一元函数继承:public unary_function<参数类型,返回类型>

    #include <iostream>
    #include <algorithm>
    #include <functional>
    #include <vector>
    using namespace std;
    
    struct MyPrint : public binary_function<int, int, void>
    {
        void operator()(int v, int val) const
        {
            cout << "v = " << v << " val = " << val << endl;
            cout << "v + val = " << v + val << endl;
        }
        
    };
    
    // 仿函数适配器 bind1st bind2nd 绑定适配器
    void test01()
    {
        vector<int> v;
        for (int i = 0; i < 10; i++)
        {
            v.push_back(i);
        }
        int addNum = 200;
        for_each(v.begin(), v.end(), bind2nd(MyPrint(), addNum));
        // 绑定适配器  将一个二元函数对象转变成一元函数对象
        // bind1st bind2nd区别?
        // bind1st,将addNum绑定为函数对象的第一个参数
        // bind2nd,将addNum绑定为函数对象的第二个参数
        cout << "----------------------" << endl;
    }
    
    struct MyPrint02
    {
        void operator()(int v)
        {
            cout << v << " ";
        }
    };
    
    struct MyCompare : public binary_function<int, int, bool>
    {
        bool operator()(int v1, int v2) const
        {
            return v1 > v2;
        }
    };
    
    struct MyGreater5 : public binary_function<int, int, bool>
    {
        bool operator()(int v, int val) const
        {
            cout << "v = " << v << " val = " << val << endl;
            return v > val;
        }
    };
    
    // 仿函数适配器 not1 not2 取反适配器
    void test02()
    {
        vector<int> v;
        for (int i = 0; i < 10; i++)
        {
            v.push_back(i);
        }
        for_each(v.begin(), v.end(), MyPrint02());
        cout << endl;
        // 正常排序 从大到小
        sort(v.begin(), v.end(), MyCompare());
        for_each(v.begin(), v.end(), MyPrint02());
        cout << endl;
        // 取反之后从小到大
        sort(v.begin(), v.end(), not2(MyCompare()));
        for_each(v.begin(), v.end(), MyPrint02());
        cout << endl;
        // not1 not2 
        // 如果对二元谓词取反,用not2
        // 如果对一元谓词取反,用not1
        vector<int>::iterator it = find_if(v.begin(), v.end(), not1(bind2nd(MyGreater5(), 11)));
        if (it == v.end())
        {
            cout << "没有找到!" << endl;
        }
        else
        {
            cout << *it << endl;
        }
        cout << "----------------------" << endl;
    }
    
    // 仿函数适配器 ptr_fun
    void MyPrint03(int val, int val2)
    {
        cout << "val = " << val << " val2 = " << val2 << endl;
        cout << "val + val2 = " << val + val2 << endl;
    }
    
    void test03()
    {
        vector<int> v;
        for (int i = 0; i < 10; i++)
        {
            v.push_back(i);
        }
        // ptr_func把普通函数转成函数对象
        for_each(v.begin(), v.end(), bind2nd(ptr_fun(MyPrint03), 10));
        cout << "--------------" << endl;
    }
    
    // 成员函数适配器 mem_fun mem_fun_ref
    class Person
    {
    public:
        Person(int age, int id) : age(age), id(id){}
        void show()
        {
            cout << "age = " << age << " id = " << id << endl;
        }
    public:
        int age;
        int id;
    };
    
    void test04()
    {
        // 如果容器中存放的对象或者对象指针,我们for_each算法打印的时候,调用类自己提供的打印函数
        vector<Person> v;
        Person p1(10, 20), p2(30, 40), p3(50, 60);
        v.push_back(p1);
        v.push_back(p2);
        v.push_back(p3);
        for_each(v.begin(), v.end(), mem_fun_ref(&Person::show));
        cout << "--------------" << endl;
        vector<Person*> v1;
        v1.push_back(&p1);
        v1.push_back(&p2);
        v1.push_back(&p3);
        for_each(v1.begin(), v1.end(), mem_fun(&Person::show));
        // mem_fun_ref mem_fun区别?
        // 如果存放的是对象指针 使用mem_fun
        // 如果使用的是对象 使用mem_fun_ref
    }
    
    int main()
    {
        test01();
        test02();
        test03();
        test04();
        getchar();
        return 0;
    }
  • 相关阅读:
    luogu P1073 最优贸易 |分层图最短路
    luogu P1901 发射站 |单调队列
    luogu P1759 通天之潜水 |背包
    luogu P1801 【黑匣子_NOI导刊2010提高(06)】|堆+分块
    bzoj1642[Usaco2007 Nov]Milking Time 挤奶时间*
    bzoj1616[Usaco2008 Mar]Cow Travelling游荡的奶牛*
    bzoj1623[Usaco2008 Open]Cow Cars 奶牛飞车*
    bzoj1612[Usaco2008 Jan]Cow Contest奶牛的比赛*
    bzoj1639[Usaco2007 Mar]Monthly Expense 月度开支*
    bzoj1601[Usaco2008 Oct]灌水*
  • 原文地址:https://www.cnblogs.com/duxie/p/10939942.html
Copyright © 2011-2022 走看看