c++仿函数浅析

来源:互联网 发布:罗伯特劳伦斯库恩知乎 编辑:程序博客网 时间:2024/06/01 21:54

在讨论仿函数之前,我们先来看看sort排序的第二种用法:

bool compare(int x,int y){return x < y;}int main(){vector<int>vec;for (int i = 0; i < 10; i++){vec.push_back(rand()%50);cout << vec[i]<<" ";}cout << endl << endl;sort(vec.begin(),vec.end(),compare);for (int i = 0; i < 10; i++)cout << vec[i]<<" ";cout << endl << endl;return 0;}


最终可以看到所有vec容器里所有的元素都按从小到大的顺序排列,在sort函数中我们将compare函数指针作为参数传递,compare函数里面指定了用户想要执行的操作,

它告诉sort务必排序后的两两相邻的元素都能令该操作为true,在compare函数中,我们希望x<y这个操作在容器vec里的任意相邻元素都为真;虽然函数指针可以达到“将整组操

作当作算法的操作”,但是它不够灵活,无法满足对抽象性的要求,于是就产生了仿函数,它其实就是一个“行为类似函数”的类对象,在这个类对象内将上述的compare函数进行

封装,下面来看看less和plus两个类的实现源码:

1. less

template<class T>struct less :public binary_function<T,T,bool>{bool operator()(const int& x, const int& y) const { return x < y; }};
2. plus

template<class T>struct plus :public binary_function<T,T,T>{T operator()(const int& x, const int& y) const { return x + y; }};

3.unary_function和binary_function

template <class _Arg, class _Result>  struct unary_function {      typedef _Arg argument_type;      typedef _Result result_type;  };    // 二元函数,模板参数:参数1的类型,参数2的类型,返回值类型。  // 注意参数的位置,如果它被继承,主要是提供了3个typedef。  template <class _Arg1, class _Arg2, class _Result>  struct binary_function {      typedef _Arg1 first_argument_type;      typedef _Arg2 second_argument_type;      typedef _Result result_type;  };  


有了仿函数之后,我们在排序的时候就只需要向sort的第三个参数传递一个函数对象即可:

int main(){vector<int>vec;for (int i = 0; i < 10; i++){vec.push_back(rand()%50);cout << vec[i]<<" ";}cout << endl << endl;less<int>le;sort(vec.begin(),vec.end(),le);for (int i = 0; i < 10; i++)cout << vec[i]<<" ";cout << endl << endl;return 0;}

下面以bind2nd来说明:

int main(){vector<int>vec;for (int i = 0; i < 10; i++){vec.push_back(rand()%100);cout << vec[i]<<" ";}cout << endl << endl;less<int>le;cout << count_if(vec.begin(),vec.end(),not1(bind2nd(le,50))) << endl;return 0;}

下面是bind2nd的源码:

template<class _fn2,class _ty> inline binder2nd<_fn2> bind2nd(const _fn2& _func, const _ty& _right){   // return a binder2nd functor adapter  typename _fn2::second_argument_type _val(_right);//此处将仿函数multiplies<int>临时对象的第二个参数设置为10  return (_std binder2nd<_fn2>(_func, _val));  //返回模板类binder2nd临时对象  }template<class _fn2>class binder2nd: public unary_function<typename _fn2::first_argument_type,typename _fn2::result_type> {  //public:typedef unary_function<typename _fn2::first_argument_type,typename _fn2::result_type> _base;typedef typename _base::argument_type argument_type;typedef typename _base::result_type result_type;binder2nd(const _fn2& _func,const typename _fn2::second_argument_type& _right)  //构造函数,仿函数第二个参数被赋值  : op(_func), value(_right){   // construct from functor and right operand  }result_type operator()(const argument_type& _left) const  //调用仿函数  {   // apply functor to operands  return (op(_left, value));}result_type operator()(argument_type& _left) const{   // apply functor to operands  return (op(_left, value));}protected:_fn2 op;    // the functor to apply  typename _fn2::second_argument_type value;  // the right operand  };


下面是个人试验:

template<class T>void func(T x,int y){ //获得x(less<int>)的型别typedeftypename T::second_argument_type type;type cc=y;cout << x(1,2) << endl;cout << sizeof(cc) << endl;cout << cc << endl;}int main(){vector<int>vec;for (int i = 0; i < 10; i++){vec.push_back(rand()%100);cout << vec[i]<<" ";}cout << endl << endl;less<int>le;int b = 9;func(le, 9);sort(vec.begin(),vec.end(),le);for (int i = 0; i < 10; i++){cout << vec[i] << " ";}return 0;}








0 0