C++ 有哪些奇淫巧技之仿函数

版权声明:本文为博主原创文章,转载请注明原文地址:http://blog.csdn.net/helloworld_ptt https://blog.csdn.net/helloworld_ptt/article/details/80743383

一、理论:

1.C++仿函数本质上是一个类,而不是一个函数.
2.其实现方式是对class的()操作符重载,让其拥有类似于函数的功能


二、仿函数应用场景:

若需要用count_if对一个vector<`string>进行字符串长度小于10的计数,你的代码可能是这样的:
幼年期:

bool cmp(const string& str1) {
     return str1.length() < 10;    
}

成长期(全局变量)是这样的:

uint_32 len;
bool cmp(const string& str1) {
     return str1.length() < len;    
}

实际上这段代码是不规范的:

1.容易出错 : 必须先初始化len,才能正确使用cmp.否则会得到不确定的答案
2.没有拓展性 : 全局变量的命名空间污染
3.全局变量问题 : 全局变量cost太高


完全体(带参函数)是这样的:

bool cmp(const string& str1, uint_32 len) {
     return str1.length() < len;    
}
count_if(vec.begin(), vec.end(), cmp); //ERROR

但是多参函数不符合需求
我们来看看C++源码

template <class InputIterator, class UnaryPredicate>
  typename iterator_traits<InputIterator>::difference_type
    count_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
  typename iterator_traits<InputIterator>::difference_type ret = 0;
  while (first!=last) {
    if (pred(*first)) ++ret;            //这一行明显只传了一个*InputIterator
    ++first;
  }
  return ret;  
}

这时候,很多童鞋可能就会想,为什么不能把多个参数糅合到一起呢?
实际上,仿函数就是做了一件这个事情:
仿函数其本质是类,这决定了仿函数能拥有一个我称其为’组合参数’的东西——成员变量.

三、仿函数的实现

究极体(成员变量)

class StringFilter{
    public:
        explicit StringFilter(uint_32 lenth) : len(lenth){}

        bool operator() (const string& str) const{
             return str.length() < len;
        }

    private:
        const uint_32 len;  
};

使用仿函数(functor):

count_if(vec.begin(), vec.end(), StringFilter(length));

类似的还有回调函数,lambda表达式值得大家去探讨.
本文少部分引用dnbc66博客:https://www.cnblogs.com/decade-dnbc66/p/5347088.html
有关于lambda表达式与仿函数的区别,可以移步:https://blog.csdn.net/anzhsoft/article/details/17463805

猜你喜欢

转载自blog.csdn.net/helloworld_ptt/article/details/80743383
今日推荐