我正在读一本书来学习C++(来自python背景).我写过这个,有效:
class CatalogueItem
{
public:
CatalogueItem();
CatalogueItem(int item_code, const string &name, const string &description);
~CatalogueItem() {};
bool operator< (const CatalogueItem &other) const;
...
private:
...
};
...
list<CatalogueItem> my_list;
// this is just me playing around
CatalogueItem items[2];
items[0] = CatalogueItem(4, string("box"), string("it's a box"));
items[1] = CatalogueItem(3, string("cat"), string("it's a cat"));
my_list.push_back(items[0]);
my_list.push_back(items[1]);
my_list.sort();
Run Code Online (Sandbox Code Playgroud)
我正在尝试的部分是使用运算符<来允许列表自行排序.
这一切似乎都很好,但http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Operator_Overloading似乎建议避免这样做,这正是本书所说的!("特别是,不要重载operator ==或operator <只是为了让你的类可以用作STL容器中的键;相反,你应该在声明容器时创建相等和比较functor类型.")
我理解"创建相等和比较函子类型"意味着创建比较函数,如下所示:
bool my_comparison_function(const CatalogueItem &a, const CatalogueItem &b)
{
// my comparison code here
}
Run Code Online (Sandbox Code Playgroud)
风格指南是指什么?
有没有人可以选择哪种方法更"正确"?
Ĵ
Ecl*_*pse 10
仿函数类型更像是这样的:
struct CatalogueItemLessThan
{
bool operator()(const CatalogueItem &a, const CatalogueItem &b)
{
}
};
Run Code Online (Sandbox Code Playgroud)
然后用法如下:
list<CatalogueItem> my_list;
// this is just me playing around
CatalogueItem items[2];
items[0] = CatalogueItem(4, string("box"), string("it's a box"));
items[1] = CatalogueItem(3, string("cat"), string("it's a cat"));
my_list.push_back(items[0]);
my_list.push_back(items[1]);
my_list.sort(CatalogueItemLessThan());
Run Code Online (Sandbox Code Playgroud)
这样做的主要优点是允许您将排序与对象本身分离.您现在可以根据需要提供多种类型的排序,并在不同的位置使用它们.(例如,字符串可以按词汇顺序排序,或者不区分大小写,或" 自然地 " 排序.
使用仿函数而不是松散函数的优点是,您可以将参数传递给比较以修改仿函数的行为方式.
一般来说,谷歌风格指南并不是真正最好的风格指南(恕我直言,特别是他们对异常的例外,但这是另一个讨论).如果一个对象有明显的排序顺序,我经常添加一个默认值operator<.如果以后,我想添加额外的排序顺序,那么我添加了松散的函数.如果以后我需要在排序顺序中添加参数,那么我将它们变成仿函数.在需要之前添加复杂性是没有意义的.
谷歌试图对你说的是以下内容.
如您所知,对于给定类型,您可以重载一个且只有一个运算符'<'.让我们说它适合你.但想象一下,将来您可能需要根据其他一些比较标准对相同类型的对象进行排序.你打算怎么做?唯一可用的"<"版本已经被采用.
当然,您可以通过编写新的命名比较函数/函数(不是'<'运算符)并将其显式提供给排序算法来实现.你可以写2个,5个,10个以上.您可以根据需要编写任意数量的内容.它会工作.但是,在这一点上,代码中会出现明显的不对称.一个比较函数实现为'operator <'.其他 - 作为不同的命名函数/仿函数.这种不对称有充分的理由吗?
好吧,可能会有.如果您有一个非常明确且明显的自然排序方法适用于您的类型,那么将它实现为运算符'<'非常有意义.这将是主要的比较方法.而其他辅助的,较少"自然"的比较方法可以而且应该被实现为命名函数.这完全没问题.
但是,如果你没有这样一个明显的"自然"比较候选人怎么办?在这种情况下,有利于一种方法优于另一种方法并且在任意选择的方法上"浪费""<"运算符并不是一个好主意.在这种情况下,建议单独留下'<',并坚持使用命名函数/仿函数.
换句话说,通过重载'<',您可以为给定类型创建"最喜欢的"比较.如果这就是你真正想要的 - 继续前进吧.但请记住,在许多情况下,创造一个人为的和任意的"最爱"并不是一个好主意.不要急于选择喜欢的过程.不要过早地使用'<'.