C++中仿函数/函数对象,函数指针的用法
2016-12-06 21:44
246 查看
研究这个起因是这样的,就是今天在用priority_queue的时候,需要自定义比较函数,但是此时又不能修改需要比较的类的内容(即不能用重载<的方法),所以只能写在外面,但是发现这样并不能编译通过。报的错叫cmp(我写的那个比较函数)不是类型名。后来查了下资料发现,这个需要用比较类去完成,比较类需要重载()方法,所以这个事情就非常引起我的好奇,想要知道一下,为什么sort这样的函数就可以直接用函数名,而priority_queue就不行呢
就像,下面的就是一个比较类:
跟priority_queue类似的带着比较函数的容器还有set和map。记住STL容器中<>里面传入的一定是类型名称,不能是具体的实例。
然后以下是正确用法的有
对于set类
注意此时一定要写*,因为用decltype来获得一个函数指针类型时,其只返回函数类型,而非指针类型,所以这个地方要显示的加上 * 表明这里是函数指针.
对于sort函数的传入
其实对于sort和set需要传进去的东西都是一致的.
只不过set中间需要定义的是类别模板而不是具体的比较函数,
所以其实set里面传入函数也是可以的,只不过在<>中需要写的不是具体函数名,而是这个函数指针的类型,然后用那个具体的函数来初始化set.就像我上面写的那样.
而对于sort来说,因为其本身就是一个函数了,所以传进去具体的比较函数实例就可以.
同理,如果再sort中传入的是类型也是不可以的,所以需要传入一个具体的实例,就像上面的那个sort必须要加()来给它实例化
基本概念
首先先要了解几个概念:函数对象/仿函数,函数指针,Lambda表达式函数对象/仿函数
函数对象(function object)又叫仿函数(functor),就是重载了调用运算符()的类,所生成的对象,就叫做函数对象/仿函数。因为重载了()之后,我们就能像函数一样去使用这个类,同时类里面又可以储存一些信息,所以要比普通的函数更加灵活。就像,下面的就是一个比较类:
class comp_class { public: bool operator()(const B& a,const B& b) { return a.a < b.a; } };
函数指针
首先,函数指针也是一个函数对象,因为指针在C++中都是对象。lambda表达式
lambda表达式的用法,我单独放偏博客来讲吧,这个坑先留着。这里就记住lambda也是一个函数对象就行了。STL函数和STL容器
开头说到的sort就是STL函数(STL function),而priority_queue就是STL容器(STL containers)。跟priority_queue类似的带着比较函数的容器还有set和map。记住STL容器中<>里面传入的一定是类型名称,不能是具体的实例。
程序例子
回到我们最开始的问题上,以set和sort为例class B {
public:
int a;
int b;
B(int _a,int _b):a(_a), b(_b) {};
};
class comp_class { public: bool operator()(const B& a,const B& b) { return a.a < b.a; } };
const bool comp_function(const B& a,const B &b) {
return a.a < b.a;
}
然后以下是正确用法的有
对于set类
//传入比较类的 set<B, comp_class> A_set; set<B, comp_class> A_set(comp_class ()); //传入函数指针的 set<B, const bool(*)(const B& a, const B &b)> A_set(comp_function);//记住参数一定要严格匹配,包括const //还可以这么写,简化声明, set<B, decltype(comp_function)*> A_set(comp_function);
注意此时一定要写*,因为用decltype来获得一个函数指针类型时,其只返回函数类型,而非指针类型,所以这个地方要显示的加上 * 表明这里是函数指针.
对于sort函数的传入
//传入比较类的 sort(A_vector.begin(), A_vector.end(),comp_class()); //注意后面的括号一定不能省略 //传入函数指针的 sort(A_vector.begin(), A_vector.end(),comp_function);
结论
所以开头中提到的问题,这里其实就已经非常明白了,我在查资料的时候,一直就坑在了这个地方,后来恍然大悟.其实对于sort和set需要传进去的东西都是一致的.
只不过set中间需要定义的是类别模板而不是具体的比较函数,
所以其实set里面传入函数也是可以的,只不过在<>中需要写的不是具体函数名,而是这个函数指针的类型,然后用那个具体的函数来初始化set.就像我上面写的那样.
而对于sort来说,因为其本身就是一个函数了,所以传进去具体的比较函数实例就可以.
同理,如果再sort中传入的是类型也是不可以的,所以需要传入一个具体的实例,就像上面的那个sort必须要加()来给它实例化
相关文章推荐
- Boost.Bind用法详解(一) 2008-05-09 15:50:50| 分类: C++ |字号 订阅 Boost.Bind 为函数和函数对象提供了一致的语法,对于值语义和指针语义也一样。
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- C++学习笔记(13)——利用对象、引用、指针调用虚函数
- typedef函数指针的用法(C++)
- C++指针探讨 函数对象
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- (转)关于C++中函数指针的使用(包含对typedef用法的讨论)
- C++成员函数指针及C++函数对象
- C++函数对象与函数指针不同之处
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- C++指针探讨 (四) 函数对象
- C++指针探讨 (四) 函数对象
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- C++指针探讨 函数对象
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- 条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引用 (转自effective c++ second edition)