part5:仿函数,仿函数类(一)
2016-07-17 20:33
337 查看
Rule38:把仿函数类设计为用于值传递
Rule39:用纯函数做判断式
一个行为良好的operator()当然是const,但不只如此。它也得是一个纯函数。不要修改内部成员对象的值,否则会出现未定义的情况。要记住纯函数没有状态,良好的operator也没有。判断式和判断式对象的operator()都是没有状态的。
Rule40:使用仿函数类可适配
关于仿函数,仿函数类我们主要讲解这一部分。我们看,如下的例子:
我们有如下代码,找到第一个有趣的Widget。
我们通过这种方法是可以的,这是基于仿函数,其实参数isInteresting这是一个函数指针。
现在如果我想要找第一个指向不有趣的Widget的指针,显而易见的方法却编译失败:
我们需要对isInteresting应用ptr_fun在应用not1之前。
ptr_fun做的唯一的事是使一些typedef有效。not1需要这些typedef,这就是为什么可以把not1应用于ptr_fun,但不能直接对isInteresting应用not1。因为是第几的函数指针,isInteresting缺乏not1需要的typedef。
四个标准函数适配器(not1,not2,bind1st,bind2nd)都需要存在某些typedef。我们应该使调用简单,我们不需要知道任何关于那些typedef的事情。operator()带一个实参的仿函数类,要继承的结构是std::unary_function。operator()带有两个实参的仿函数类,要继承的结构是std::binary_function。
unary_function一元,binary_function二元,模板化的最后一个参数与operator()的返回值相同
MeetsThreshold是一个类,而WidgetNameCompare是一个结构。因为一元MeetsThreshold可以有内部状态值,而类是封装那些信息的合理办法。WidgetNameCompare没有状态,因此不需要任何private东西。
Rule41:了解使用ptr_fun,memfun。
我们知道如下调用是合理的。
对vw的每个元素调用test方法。
如果test是一个Widget的成员函数,而不是一个非成员函数,像这样。
我们期待这么调用:
但是,STL期待的调用形式就是使用非成员函数的语法形式调用。
所以mem_fun产生了,他们让成员函数可以那么调用。
mem_fun带有一个到成员函数的指针pmf,并返回一个mem_fun_t类型的对象。这是一个仿函数类,容纳成员函数指针并提供一个operator(),它调用指向在传给operator()的对象上的成员函数。
正确使用方法如下:
Rule39:用纯函数做判断式
一个行为良好的operator()当然是const,但不只如此。它也得是一个纯函数。不要修改内部成员对象的值,否则会出现未定义的情况。要记住纯函数没有状态,良好的operator也没有。判断式和判断式对象的operator()都是没有状态的。
Rule40:使用仿函数类可适配
关于仿函数,仿函数类我们主要讲解这一部分。我们看,如下的例子:
我们有如下代码,找到第一个有趣的Widget。
class Widget{ //测试用不需要内容 public: int id; Widget(int id) { this->id = id; } }; bool isInteresting(const Widget* pw) { if (pw->id == 2) { return true; } return false; } list<Widget*> lwptrs; lwptrs.push_back(new Widget(1)); lwptrs.push_back(new Widget(2)); list<Widget*>::iterator it = find_if(lwptrs.begin(),lwptrs.end(),isInteresting);
我们通过这种方法是可以的,这是基于仿函数,其实参数isInteresting这是一个函数指针。
现在如果我想要找第一个指向不有趣的Widget的指针,显而易见的方法却编译失败:
list<Widget*>::iterator it = find_if(lwptrs.begin(),lwptrs.end(),not1(isInteresting));
我们需要对isInteresting应用ptr_fun在应用not1之前。
list<Widget*>::iterator it = find_if(lwptrs.begin(),lwptrs.end(),not1(ptr_fun(isInteresting)));
ptr_fun做的唯一的事是使一些typedef有效。not1需要这些typedef,这就是为什么可以把not1应用于ptr_fun,但不能直接对isInteresting应用not1。因为是第几的函数指针,isInteresting缺乏not1需要的typedef。
四个标准函数适配器(not1,not2,bind1st,bind2nd)都需要存在某些typedef。我们应该使调用简单,我们不需要知道任何关于那些typedef的事情。operator()带一个实参的仿函数类,要继承的结构是std::unary_function。operator()带有两个实参的仿函数类,要继承的结构是std::binary_function。
template<typename T> class MeetsThreshold: public std::unary_function<Widget, bool>{ private: const T threshold; public: MeetsThreshold(const T& threshold); bool operator()(const Widget&) const; ... }; struct WidgetNameCompare: public std::binary_function<Widget, Widget, bool>{ bool operator()(const Widget& lhs, const Widget& rhs) const; };
unary_function一元,binary_function二元,模板化的最后一个参数与operator()的返回值相同
MeetsThreshold是一个类,而WidgetNameCompare是一个结构。因为一元MeetsThreshold可以有内部状态值,而类是封装那些信息的合理办法。WidgetNameCompare没有状态,因此不需要任何private东西。
Rule41:了解使用ptr_fun,memfun。
我们知道如下调用是合理的。
void test(Widget &w); vector<Widget> vw; for_each(vw.begin(),vw.end(),test);
对vw的每个元素调用test方法。
如果test是一个Widget的成员函数,而不是一个非成员函数,像这样。
class Widget{ public: void test(); };
我们期待这么调用:
for_each(vw.begin(),vw.end(),&Widget::test);
但是,STL期待的调用形式就是使用非成员函数的语法形式调用。
所以mem_fun产生了,他们让成员函数可以那么调用。
template<typename R, typename C> // 用于不带参数的non-const成员函数 mem_fun_t<R,C> // 的mem_fun声明。 mem_fun(R(C::*pmf)()); // C是类,R是被指向 // 的成员函数的返回类型
mem_fun带有一个到成员函数的指针pmf,并返回一个mem_fun_t类型的对象。这是一个仿函数类,容纳成员函数指针并提供一个operator(),它调用指向在传给operator()的对象上的成员函数。
正确使用方法如下:
for_each(lpw.begin(), lpw.end(), mem_fun(&Widget::test));
相关文章推荐
- 条件预编译/tyordef/结构体
- MATLAB 读取csv
- python爬虫(1)——BeautifulSoup库函数find_all()
- Palindromes
- docker搭建apache+php+mysql
- Drools(JAVA规则引擎)开发指南
- 第12章 正则表达式与文件格式化处理
- POJ-3070 Fibonacci(矩阵快速幂求Fibonacci数列)
- 区间or值(移位)
- 指针---练习题
- 算法导论 16.1-1
- win10 获取超级管理员权限
- 时间格式类型互转之 字符串、日历、时间数据
- 山东理工OJ 1171 C语言实验——保留整数
- 【Ubuntu】输出terminal log到文件
- RxJava入门七问(一)
- ORACLE基本数据类型总结
- android 五大布局-线性布局(LinearLayout)
- ASP.NET身份认证
- 一个看错题面带来的问题——最小标号最短路