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

    1、考虑下面的需求,从集合中找到一个与当前Student相等的学生,如下:
    int main(int argc, char* argv[])
    {
    Student s1(20,"Andy");
    Student s2(23,"Bill");
    Student s3(28,"Caroline");
    Student s4(27,"David");
    Student s5(21,"Eric");

    vector<Student> stuVec;
    stuVec.push_back(s1);
    stuVec.push_back(s2);
    stuVec.push_back(s3);
    stuVec.push_back(s4);
    stuVec.push_back(s5);

    Student target(23,"Bill");

    vector<Student>::iterator iter = find(stuVec.begin(),stuVec.end(),target);

    return 0;
    }
    注意:调用find方法,Student要重载成员操作符==,或者重载普通操作符==,因为find使用==比较两个对象是否相等。
    2、需求变更,找出一个年龄比target大的学生,怎么办?
    使用函数对象,函数对象有一个成员_stu,使用target初始化_stu,重载(),比较target与序列中的每个对象
    class Finder
    {
    public:
    Finder(const Student& stu):_stu(stu)
    {

    }

    bool operator()(const Student& rhs)
    {
    if(rhs._Age>_stu._Age)
    {
    return true;
    }
    return false;
    }

    private:
    Student _stu;
    };

    iter = find_if(stuVec.begin(),stuVec.end(),Finder(target));
    注:假如对于teacher的集合,也要同样的需求,找出一个年龄比target大的教师,可以将Finder修改成模板类。

    3、有没有其他的办法呢?
    使用greater<Student>可以比较Student的大小,一个是变量,一个是参照物,而find_if的第三个参数,隐式接口是 Pred(*First),只接受一个参数。
    使用bind2nd 对greater<Student>和参照物封装,对外暴露接口接受一个参数,对内调用greater(参数,参照物),greater使用>比较大小,对Student进行>操作符过载。
    bool operator>(const Student& lhs,const Student& rhs)
    {
    return lhs._Age > rhs._Age;
    }

    iter = find_if(stuVec.begin(),stuVec.end(),bind2nd(greater<Student>(),target));

    4、其他办法呢?
    不过载操作符,偏特化一个greater,用于比较age大小。如下:
    template <>
    struct greater<Student>: public binary_function<Student, Student, bool>
    {
    bool operator()(const Student& _Left, const Student& _Right) const
    {
    return (_Left._Age > _Right._Age);
    }
    };
    iter = find_if(stuVec.begin(),stuVec.end(),bind2nd(greater<Student>(),target));
    5、因为偏特化只有一个,能不能自己写一个类似greater的方法对象呢,并且是可以使用bind2nd适配的。
    注意:为了可适配,需要继承 public binary_function<Student, Student, bool>
    struct StudentNameCompare: public binary_function<Student, Student, bool>
    {
    bool operator()(const Student& _Left, const Student& _Right) const
    {
    return (_Left._Age > _Right._Age);
    }
    };
    iter = find_if(stuVec.begin(),stuVec.end(),bind2nd(StudentNameCompare(),target));

    当然也可以使用模板,如下:
    template <typename T>
    struct StudentNameCompare: public binary_function<T, T, bool>
    {
    bool operator()(const T& _Left, const T& _Right) const
    {
    return (_Left._Age > _Right._Age);
    }
    };
    iter = find_if(stuVec.begin(),stuVec.end(),bind2nd(StudentNameCompare<Student>(),target));

    6、现在分析2的方法和5的方法,最终的接口都要满足 Pred(*First),只接受一个参数。二者的处理策略不同。 在2中,函数对象,只接受一个参数,但是有一个字段,这个字段用于保存参照物。在5中,函数对象接受两个参数,继承binary_function,使之可适配,然后使用bind2nd 将函数对象和参照物封装起来,对外暴露接口只接受一个参数。
    7、考虑下面的需求,找出一个年龄比target小的学生,对于5,只需要使用not1再次适配一下即可,如下:
    iter = find_if(stuVec.begin(),stuVec.end(),not1(bind2nd(StudentNameCompare<Student>(),target)));
    但是对于2,不行。因为2不是可适配的,要让2是可适配的,需要继承 public unary_function<Student,bool>,如下:
    class Finder:public unary_function<Student,bool>
    {
    public:
    Finder(const Student& stu):_stu(stu)
    {

    }

    bool operator()(const Student& rhs) const
    {
    if(rhs._Age>_stu._Age)
    {
    return true;
    }
    return false;
    }

    private:
    Student _stu;
    };
    当然,也可以使用模板。

  • 相关阅读:
    HTTP 03 HTTP 报文头
    HTTP 02 HTTP1.1 协议
    HTML 01 请求过程
    Java_异常_04_ OutOfMemoryError系列
    mq_学习_01_消息中间件的概述
    mq_学习_00_资源帖
    Java钉钉开发_异常_01_error code:50002, error message:请求的员工userid不在授权范围内
    Java_JS_01_java调用js
    JavaUtil_09_email_使用 commons-email 发送邮件
    JavaUtil_08_StringUtil_commons-lang3 之 StringUtils
  • 原文地址:https://www.cnblogs.com/nzbbody/p/4622825.html
Copyright © 2011-2022 走看看