函数对象存在的意义
假设有一个类型为vector<int>的对象,我们想找出其中第一个大于100的元素对应的迭代器,显然我们可以使用如下方法
find_if(v.begin(), v.end(), greater100);
其中greater100是一个函数指针,这个指针对应的函数定义如下
bool greater100(int n) { return n > 1000; }
上述功能实现非常简单,我们使用函数指针就轻松解决了问题,但如果新的需求来了,比如我们还想找出第一个大于100的元素,那我们必须新定义一个新的函数,在这种情况下,一旦新的需求出现,我们必须新定义一个相似却不相同的函数
这太麻烦了,C++中解决这类问题的办法是使用函数对象,这个解决方法相当优雅高效,代码如下:
find_if(v.begin(), v.end(),bind2nd(greater<int>(), x) //设置好需要的x的值即可
先来看看预定义函数符的源码,在头文件functional能找到如下代码(VS):
template<class _Ty> struct greater : public binary_function<_Ty, _Ty, bool> { // functor for operator> bool operator()(const _Ty& _Left, const _Ty& _Right) const { // apply operator> to operands return (_Left > _Right); } }; //预定义函数符的基类 template<class _Arg1, class _Arg2, class _Result> struct binary_function { // base class for binary functions typedef _Arg1 first_argument_type; typedef _Arg2 second_argument_type; typedef _Result result_type; };我们自定义的函数对象模板依葫芦画瓢即可,在后面的实例代码中我自定义了一个Plus函数对象模板
按照上面这种形式定义的函数对象模板都定义了成员first_argument_type,second_argument_type和result_type,实际中这些成员都是放在一个基类模板binary_function中,它们的作用不不言而喻;这几个成员的定义与函数对象需要与函数对象模板bind1st和bind2nd需要进行配合有关,比如bind1st类模板的大致框架如下:
template<T> //仅为说明原理,具体VS的C++库中的源码与此不同 class bind1st { bind1st(const T&, const T::first_argument_type&); T::result_type operator() (const T::second_argument_type); //... }自定义Plus函数对象模板的完整示例代码如下:
#include <iostream> //#include <algorithm> #include <functional> using namespace std; template <class T> class Plus: public binary_function<T,T,T> { public: const T& operator()(const T& n1, const T& n2) const { return n1 + n2; } }; void main() { Plus<int> a; cout << a(1,2) << endl; binder1st<Plus<int> > c = bind1st(a,2); //验证与bind1st结合有效性 cout << c(2) << endl; Plus<int>::result_type i = 5; //验证是否result_type等的存在 cout << i << endl; }运行结果如下:
3
4
5