C++中的function object

 

Function object定义:
    Function object是一个对象,不过它的行为表现像函数。一般而言,它是由一个重载了operator()的类所实例化得来的对象。
    Function object的涵义比通常意义上的函数更广泛,因为它可以在多次调用之间保持某种“状态”——这和静态局部变量有异曲同工之妙;不过这种“状态”还可以被初始化,还可以从外面来检测,这可要比静态局部变量强了。我们来看一个例子:

  1. class Sum {
  2.   int val;
  3.  public:
  4.   Sum(int i) :val(i) { }
  5.   operator int() const { return val; }  // extract value
  6.   int operator()(int i) { return val+=i; } // application
  7.  };
  8.  void f(vector<int> v)
  9.  {
  10.   Sum s = 0; // initial value 0
  11.   s = for_each(v.begin(), v.end(), s); // gather the sum of all elements
  12.   cout << "the sum is " << s << "/n";
  13.   // or even:
  14.   cout << "the sum is " << for_each(v.begin(), v.end(), Sum(0)) << "/n";
  15.  }

    这里我要提请大家注意:一个function object可被漂亮地内联化(inlining),因为对于编译器而言,没有讨厌的指针来混淆视听,所以这样的优化很容易进行。[译注:这指的是将operator()定义为内联函数,可以带来效率的提高。] 作为对比,编译器几乎不可能通过优化将“通过函数指针调用函数”这一步骤所花的开销省掉,至少目前如此。
在标准库中function objects被广泛使用,这给标准库带来了极大的灵活性和可扩展性。

 

下面再看一个例子:

  1.   #include <iostream>
  2.    #include <vector>
  3.    #include <algorithm>
  4.    using namespace std;
  5.  void printInt (int elem)
  6.    {
  7.        cout << elem << ' ' ;
  8.    }
  9.    int main()
  10.    {
  11.        vector<int> coll;
  12.        //insert elements from 1 to 9
  13.        for (int i=1; i<=9; ++i) {
  14.            coll.push_back(i); 
  15.        }
  16.        //print all elements
  17.        for_each (coll.begin(), coll.end(),printInt);            
  18.        cout << endl;
  19.    }

对于这个例子,for_each()的第三个参数,调用了printInt这个函数。在看下面的例子:

  1. #include <iostream>
  2.    #include <vector>
  3.    #include <algorithm>
  4.    using namespace std;
  5.    //simple function object that prints the passed argument
  6.    class PrintInt {
  7.      public:
  8.        void operator() (int elem) const {
  9.            cout << elem << ' ';
  10.        }
  11.    };
  12.    int main()
  13.    {
  14.        vector<int> coll;
  15.        //insert elements from 1 to 9
  16.        for (int i=1; i<=9; ++i) {
  17.            coll.push_back(i);
  18.        }
  19.        //print all elements
  20.        for_each (coll.begin(), coll.end(),    PrintInt()); 
  21.        cout << endl;
  22.    }

在这个例子中,for_each()的第三个参数就是函数对象。

那么这到底有什么区别呢?也许从上面的代码中还看不出,但是,请继续看下面的例子:

  1. //对每一个element加10;
  2. void add10 (int& elem)
  3.    {
  4.        elem += 10;
  5.    }
  6.    void fl()
  7.    {
  8.        vector<int> coll;
  9.        ...
  10.        for_each (coll.begin(), coll.end(),   add10);                   
  11.    }

这样看起来似乎很好,但是,如果突然要求变了,要求对每一个element改成加9;那么,可能想到的办法是改写函数

void add9 (int& elem)
   {
       elem +=9;
   }

哦,那么要求又改成+8、+7…… -3等等,总不至于对于每一个都重新写一个函数吧?虽然可行,但是违背

范型变成的思想。也许有新的办法:

  1. template <int theValue>
  2.    void add (int& elem)
  3.    {
  4.        elem += theValue;
  5.    }
  6. void f1()
  7.    {
  8.        vector<int> coll;
  9.        ...
  10.        for_each (coll.begin() , coll.end(),     //range
  11.                  add<10>);                      //operation
  12.    }

但是,如果连类型(int)都变了(如改成float),那该怎么实现呢?哦,用一般的函数应该不能实现了吧?

但是如果用function object思想,就可以实现,看下面的代码:

  1. template <class T>
  2. class AddValue {
  3.       private:
  4.         T theValue;      
  5.        public:
  6.             AddValue(T v) : theValue(v) {
  7.         }
  8.             void operator() (T& elem) const {
  9.             elem += theValue;
  10.         }
  11.    };

现在这个类就可以实现多个类型的相加形式了。

因此可以总结在用函数对象时,可以更加满足了STL的范型编程思想。

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值