代码之家  ›  专栏  ›  技术社区  ›  Darius Kucinskas

从std::binary_函数(或std::unary函数)继承的好处是什么?

  •  27
  • Darius Kucinskas  · 技术社区  · 15 年前

    从std::binary_函数(或std::unary_函数)继承的好处是什么?

    例如,我有这样的代码:

    class Person
    {
     public:
        Person();
        Person(int a, std::string n);
        Person(const Person& src);
    
        int age;
        std::string name;
     };
    
     Person::Person()
               : age(0)
                 , name("")
                   {};
    
     Person::Person(int a, std::string n)
     : age(a)
     , name(n)
     {};
    
     Person::Person(const Person& src)
     {
       age = src.age;
       name = src.name;
     };
    
     struct PersonPrint : public std::unary_function<Person, void>{
       void operator() (Person p){
         std::cout << " Person age: " << p.age 
                   << " name: " << p.name << std::endl;
       }
     };
    
     struct PersonGreater : public std::binary_function<Person, Person, bool>{
       bool operator()(const Person& p1, const Person p2){
         if (p1.age > p2.age) return true;
         if (p1.name.compare(p2.name) > 0) return true;
         return false;
       }
     };
    
     int main(int count, char** args)
     {
       std::vector<Person> personVec;
       Person p1(10, "Person1");
       Person p2(12, "Person2");
       Person p3(12, "Person3");
    
       personVec.push_back(p1);
       personVec.push_back(p2);
       personVec.push_back(p3);
    
       std::cout << "before sort: " << std::endl;
       std::for_each(personVec.begin(), personVec.end(), PersonPrint());
       std::sort(personVec.begin(), personVec.end(), PersonGreater());
       std::cout << "after: " << std::endl;
       std::for_each(personVec.begin(), personVec.end(), PersonPrint());
     }
    

    但是我也可以在没有继承形式的情况下编写这个代码 std::unary_function/std::binary_function ?

     struct PersonPrint {
         void operator() (Person p) {
             std::cout << " Person age: " << p.age << " name: " << p.name << std::endl; 
         } 
     }; 
    
     struct PersonGreater {
         bool operator()(const Person& p1, const Person p2) {
             if (p1.age > p2.age) return true; 
             if (p1.name.compare(p2.name) > 0) return true; 
             return false; 
         } 
     };
    

    更新的

    STD::二进制函数和STD::unAyl函数被禁止为C++ 11,请参见@ AlexandreC注释。

    4 回复  |  直到 10 年前
        1
  •  29
  •   Mykola Golubyev    15 年前

    从[一元二进制]_函数继承只会在类中为您提供一个额外的typedef:

    对于一元函数

    argument_type
    result_type
    

    对于二元函数

    first_argument_type
    second_argument_type
    result_type 
    

    这些类型是传递给[一元二进制]_函数的类型。 在你的情况下没有好处。

    如果要将函数与其他std函数修改器(如not1、bind1st)一起使用,则必须从[unart binart]_函数继承。

    如果您要为自己的目的存储这个模板信息,最好使用现成的解决方案。

        2
  •  16
  •   MSalters    15 年前

    除了typedef(已经提到),还有可读性方面。当我看到 struct Foo {... 我的第一个想法是“foo是一种类型”。但与 struct Foo : public unary_function<... 我已经知道foo是一个函数。对于程序员(与编译器不同),类型和函数是非常不同的。

        3
  •  9
  •   Johannes Schaub - litb    15 年前

    就像Mykola解释的那样,他们只是在添加typedef。想象一下你的 PersonGreater ,您要修复某个人的第一个参数。这个 binder1st 需要将第一个参数存储在某个地方,因此它需要第一个参数的类型。 binary_function 以typedef形式提供:

    // get a function object that compares person1 against 
    // another person
    std::bind1st(PersonGreater(), person1)
    

    现在,返回的 宾达1号 对象知道它需要存储的参数类型是Person类型。

    一些函数对象否定另一个函数对象的结果。这里我们也需要参数的类型:

    template <class Predicate>
    class unary_negate
        : public unary_function<typename Predicate::argument_type,bool> {
        Predicate pred;
    public:
        explicit unary_negate(const Predicate& pred):pred(pred) { }
        bool operator()(const typename Predicate::argument_type& x) const {
            return !pred(x);
        }
    };
    

    也可以使用模板 operator() 但标准规定使用 argument_type 键入作为参数。求反器本身是从一元函数派生的,无论如何都需要提供第一个参数类型。

    有时,人们试图使用 [unary,binary]_function 存储函数对象/指针。但是,它们不能用于此目的。 boost::function 完成这项工作,并将在下一个标准中采用 std::function .

        4
  •  3
  •   JohnMcG    15 年前

    它是编译器强制执行的一种强大的文档形式。

    通过继承,您承诺将实现二进制_函数接口,编译器将支持您实现该接口。然后,客户机可以相信您的类可以在任何需要二进制_函数的地方使用。