STL 之 函数对象(函数符)

函数对象

    也叫做 函数符 (functor)。函数符是可以以函数方式与()结合使用的任意对象。这包括函数名、指向函数的指针和重载了()操作符的类对象(即定义了函数operator()()的类)。

 

    例如,这样定义一个类:
    class Linear
    { private:
         double slope,y0;
      public:
         Linear (double _sl = 1, double _y = 0):slope(_s1),y0(_y) {}
         double operator() (double x) {return y0 + slope * x;}
     };

 

    重载的()操作符将使得能够像函数那样使用Linear对象:
    Linear f1;
    linear f2 (2.5, 10.0);
    double y1 = f1 (12.5);
      // right hand side is f1.operator()(12.5)
    double y2 = f2 (0.4);

    其中y1将使用表达式0 + 1 * 12.5来计算,y2将使用表达式10.0 + 2.5 * 0.4来计算。

 

举例说明函数符调用

 

    函数for_each(),它将指定的函数用于区间中的每个成员:
    for_each(books.begin(), books.end(), ShowReview);

 

    通常,第3个参数可以是常规函数,也可以是函数符。如果把它声明为函数指针,则函数指针指定了参数类型。但由于容器可以包含任意类型,而无法预先知道将使用何种参数类型。所以STL通过使用模板来解决这个问题。


    for_each的原型:
   template<class InputIterator, class Function>
   Function for_each(InputIterator first,InputIterator last, Function f);

 

    假设ShowReview()的原型如下:
    void ShowReview (const Review &);

 

    那么,标识符ShowReview的类型将为 void (*) (const Review &),这也是赋给模板参数Function的类型。对于不同的函数调用,Function参数都可以表示具有重载的()操作符的类类型。最终,for_each()代码将具有一个使用f(...)的表达式。


    在上面范例中,f是指向函数的指针,而f(...)调用该函数。如果最后的for_each()参数是一个对象,则f(...)将是调用重载的()操作符的对象。

 

函数符概念

    生成器(generator),是不用参数就可以调用的函数符。

    一元函数(unary function),是用一个参数可以调用的函数符。

    二元函数(binary function),是用两个参数可以调用的函数符。

    (例如,提供给for_each()的函数符应当是一元函数,因为它每次用于一个容器元素。)

 

    返回bool值的一元函数是 断言 (predicate)

    返回bool值的二元函数是 二元断言 (binary predicate)

 

    list模板有一个将断言作为参数的remove_if()成员,该函数将断言应用于区间中的每个元素,如果断言返回true,则删除这些元素。

    例如,下面的代码删除链表scores中所有大于100的元素:
    bool tooBig(int n) { return n > 100; }
    list<int> scores;
    ...
    scores.remove_if(tooBig);

 

    现在假设又要删除另一个链表中所有大于200的值。就必须重新设计一个断言。如果能将取舍值作为第二个参数传递给tooBig(),则可以使用不同的值调用该函数,但断言又只能有一个参数。不过,如果设计一个tooBig类,则可以使用类成员而不是函数参数,来传递额外的信息:

    template<class T>
    class tooBig
    { private:
         T cutoff;
      public:
         tooBig (const T & t): cutoff(t) {}
         bool operator() (const T & v) { return v > cutoff; }
    };

 

    这里,一个值(V)作为函数参数传递,而第二个参数(cutoff)是由类构造函数设置的。有了该定义后,就可以将不同的tooBig对象初始化为不同的取舍值,供调用remove_if()时使用:
    scores.remove_if(tooBig<int>(200));

    函数符(tooBig<int>(200))是一个匿名对象,它是由构造函数调用创建的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值