从std :: binary_function(或std :: unary函数)继承有什么好处?

时间:2009-03-04 10:03:08

标签: c++ stl

从std :: binary_function(或std :: unary_function)继承有什么好处?

例如我有这样的代码:

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; 
     } 
 };

已更新

从p ++ 11开始,不推荐使用std :: binary_function和std :: unary_function,请参阅@AlexandreC的评论。

4 个答案:

答案 0 :(得分:29)

[unary | binary] _function的继承只会在你的类中为你提供一个额外的typedef:

对于unary_function

argument_type
result_type

对于binary_function

first_argument_type
second_argument_type
result_type 

您传递给[unary | binary] _function的那些类型。 在你的情况下,没有任何好处。

如果你打算将你的Functor与其他std Functors修饰符如not1,bind1st一起使用,你必须继承[unart | binart] _function。

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

答案 1 :(得分:16)

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

答案 2 :(得分:9)

像Mykola解释的那样,他们只是添加了typedef。想象一下,对于你的PersonGreater,你想要为某人修正第一个参数。 binder1st需要在某处存储第一个参数,因此它需要第一个参数的类型。 binary_function将其作为typedef提供:

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

现在,返回的binder1st对象知道它需要存储的参数类型是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_function,无论如何都需要提供第一个参数类型。

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

答案 3 :(得分:3)

这是编译器强制执行的强大文档形式。

通过继承,您承诺将实现binary_function接口,编译器将为您提供帮助。然后,客户可以相信,只要需要binary_function,您的类就可以使用。