一、理论:
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