0 - 前言
总的来说,为关联式容器自定义排序规则,有以下 2 种方法。
1 - 使用函数对象
无论关联式容器中存储的是基础类型(如 int、double、float 等)数据,还是自定义的结构体变量或类对象(包括 string 类),都可以使用函数对象的方式为该容器自定义排序规则。
1 - 1 什么是函数对象
如果一个类将
()
运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象。函数对象是一个对象,但是使用的形式看起来像函数调用,实际上也执行了函数调用,因而得名。
举个例子:
#include <iostream>
using namespace std;
class CAverage
{
public:
double operator()(int a1, int a2, int a3)
{
//重载()运算符
return (double)(a1 + a2 + a3) / 3;
}
};
int main()
{
CAverage average; //能够求三个整数平均数的函数对象
cout << average(3, 2, 3); //等价于 cout << average.operator(3, 2, 3);
return 0;
}
//average 是一个对象,average(3, 2, 3) 实际上就是 average.operator(3, 2, 3),这使得 average 看上去像函数的名字,故称其为函数对象。
()
是目数不限的运算符,因此重载为成员函数时,有多少个参数都可以。
1 - 2 STL中的函数对象类模板
例如,如果要求两个 double 型变量 x、y 的乘积,可以写:
multiplies<double> () (x, y)//首先用multiplies实例化了一个暂时的对象,构造该对象时传入参数x y
less 是 STL 中最常用的函数对象类模板,其定义如下:
template <class_Tp>
struct less
{
bool operator() (const_Tp & __x, const_Tp & __y) const
{
return __x < __y; }
};
//要判断两个 int 变量 x、y 中 x 是否比 y 小,可以写:
//if( less<int>()(x, y) ) { 操作 }
常用的可供关联容器使用的排序规则为:
1 - 3 使用函数对象规定容器排序规则
#include <iostream>
#include <set> // set
#include <string> // string
using namespace std;
//定义函数对象类
class cmp {
public:
//重载 () 运算符
bool operator ()(const string &a,const string &b) {
//按照字符串的长度,做升序排序(即存储的字符串从短到长)
return (a.length() < b.length());
}
};
int main() {
//创建 set 容器,并使用自定义的 cmp 排序规则
std::set<string, cmp>myset{
"http://c.biancheng.net/stl/",
"http://c.biancheng.net/python/",
"http://c.biancheng.net/java/"};
//输出容器中存储的元素
for (auto iter = myset.begin(); iter != myset.end(); ++iter) {
cout << *iter << endl;
}
return 0;
}
结果:
http://c.biancheng.net/stl/
http://c.biancheng.net/java/
http://c.biancheng.net/python/
2 - 重载关系运算符实现自定义排序
当关联式容器中存储的数据类型为自定义的结构体变量或者类对象时,通过对现有排序规则中所用的关系运算符进行重载,也能实现自定义排序规则的目的。
注意,当关联式容器中存储的元素类型为结构体指针变量或者类的指针对象时,只能使用函数对象的方式自定义排序规则,此方法不再适用。
剩余部分建议参考前言中的链接