effective stl 第40条:若一个类是函数子,则应使他可配接
来源:互联网 发布:线性时间选择算法分析 编辑:程序博客网 时间:2024/06/05 21:08
#include<iostream>#include<list>#include<algorithm>#include<functional>using namespace std;bool isInsteresting(const string* obj)//判断某个类型是否有趣{ if ((*obj)[4] % 7 == 0) { return true; } return false;}int main(){ list<string*> listString(20); for (int i = 0; i < 26; i++) { listString.push_back(new string("haha"+(i+'a'))); } //接下来找到第一个满足isInsteresting的string list<string*>::iterator i = find_if(listString.begin(), listString.end(), isInsteresting); if (i != listString.end()) { //找到满足的条件之后 } //反之,如果想找到第一个不满足isInterseting条件的string指针,下边的方法显而易见却不能通过编译 //list<string*>::iterator iN = find_if(listString.begin(), listString.end(), not1(isInsteresting)); //正确的方法是,在应用Not1之前,必须加上ptr_fun list<string*>::iterator iN = find_if(listString.begin(), listString.end(), not1(ptr_fun(isInsteresting))); if (i != listString.end()) { //doSomething } return 0;}
为什么加上ptr_fun就能编译运行了呢,问题的答案也许有些出乎意料,ptr_fun只不过完成了一些类型定义的工作,而这些类型定义是Not1所必须的。isInteresting作为一个基本的函数指针,它缺少Not1所需要的类型。
4个标准的函数配接器(not1、not2/bind1st/bind2nd(注:std::bind1st 和 std::bind2nd将二元函数转换为一元函数bind1st和bind2的使用方法详解))都有一些特殊的类型定义,那些非标准的、与STL兼容的配接器通常也是如此。提供了这些必要的类型定义的函数对象称为可配接的函数对象,反之,如果函数对象缺少这些类型对象,则称为不可配接的。
特殊的类型定义是指: argument_type、fist_argument_type、second_argument_type、result_type
除非你要编写自定义的配接器,否则你不需要知道有关这些类型定义的细节。
如果函数子类的operator()只有一个实参,那么它应该从std::unary_function继承,如果函数子类的operator()有两个实参,那么它应该从std::binary_function继承。
由于unary_function和binary_function是STL的模板,所以不能直接继承,相反,必须继承它们所产生的结构,这就要求你指定某些类型实参。对于unary_function,必须指定函数子类operator的参数类型,以及返回类型;对于Binary_function,必须指定三个类型:operator的第一个参数、operator的第二个参数和operator的返回类型。
eg:
template<typename T> class MeetsThreshold : public unary_function<string, bool>{private: const T threshold;public: MeetsThreshold(const T& threshold); bool operator()(const string&)const;};struct WidgeNameCompare : public binary_function<string, string, bool>{ bool operator()(const string& lhs,const string& rhs) const;};
注意:传递给unary_function和binary_function的模板参数这是函数子类的operator()的参数类型和返回类型,唯一可能有点奇怪的是,operaror()的返回类型是unary_function和binary_function的最后一个参数。
你可能注意到了MeetsThreshold是一个类,而WidgetNameCompare是一个结构。MeetsThreshold有内部状态(它的阈值数据成员),而类是封装那些信息的合理方法。WidgetNameCompare没有状态,因此不需要任何private的东西。所有东西都是public的仿函数类的作者经常把它们声明为struct而不是class,也许只因为可以避免在基类和operator()函数前面输入“public”。把这样的仿函数声明为class还是struct纯粹是一个个人风格问题。如果你仍然在精炼你的个人风格,想找一些仿效的对象,看看无状态STL自己的仿函数类(比如,less、plus等)一般写为struct。
再来看WidgetNameCompare虽然operator()的参数类型是const string&,但是传递给binary_function的类确实WIdget。一般情况下,传递给unary_function和binary_function的非指针类型需要去掉const和引用&。如果operator()带有指针参数,则规则就不同了,下边是widgetNameCompare含数字的另一个不同的版本
struct WidgeNameCompare : public binary_function<const string*, const string*, bool>{ bool operator()(const string*, const string*) const;};
对于以指针为参数或者返回诶性的函数子类,一般的规则是,传给unary_function或者binary_function的类型与opertor()参数和类型完全相同。
//找到最后一个不符合阈值"haha"的对象 list<string*> str1; list<string*>::reverse_iterator ri = find_if(str1.rbegin(), str1.rend(), not1(MeetsThreshold<string>("haha"))); //找到按照WidgetNameCompare的排序规则,排在s之前的第一个string对象 string s("haha"); list<string*>::iterator ri = find_if(str1.begin(), str1.end(), bind2nd(WidgeNameCompare(), s));
STL是假设每一个函数子类只有一个operator()成员函数,
当然也可以将两个operator()何在一起,但是最好不要这样做,因为这样的函数子 只有一半的配接功能,只有一半配接功能的函数子并不比完全不配接的函数子强多少。
- effective stl 第40条:若一个类是函数子,则应使他可配接
- effective stl 第39条:确保判别式是“纯函数”
- Effective stl 第6条
- effective stl 第15条
- Effective STL: 38 - 42 函数子、函数子类、函数及其他
- effective stl 第46条:考虑使用函数对象而不是函数作为STL算法的参数
- effective stl 第10条:了解分配子(allocator)的约定和限制
- effective stl 第11条 :理解自定义分配子的合理用法
- Effective stl 第一章 第7、8条
- Effective STL 第一章 第9条
- Effective stl 第一章 第10条
- Effective STL 第2、3、4条
- effective stl 第21条:总是让比较函数在等值情况下返回false
- effective stl 第38条:遵循按值传递的原则来设计函数子类
- effective stl 第44条:容器的成员函数优先于同名的算法
- Effective stl 第1章 容器 第5条
- Effective STL 第5条:区间成员函数优先于与之对应的单元素成员函数
- Effective STL 第1条:慎重选择容器类型
- 加密技术入门——从对称加密到CA证书
- Almost Union-Find(Uva 11987)并查集
- Screen用法
- win2003 DNS服务器配置方法[图文详解]
- python数据结构学习笔记-2016-10-05-02-抽象数据类型(二)
- effective stl 第40条:若一个类是函数子,则应使他可配接
- Linux Notes: alias and unalias
- 网狐 自绘 倒计时和准备按钮
- 利用FileProvider建立文件分享
- Prime Path (HDU1973/POJ3126)(B)
- MFC中CSkinImage显示PNG图片,包括大图中含有一串小图(网狐)
- js之bom_技术
- 网狐 "由于网络问题,您已经与服务器断开连接,请重新连接"
- 45. Jump Game II