用运算符覆盖排序没有得到我想要的
sort with operator overriding does not get I want
我正在尝试按 person.name 和年龄对人物向量进行排序。因此,我试图覆盖 Person
定义中的 operator<
,并将仿函数与 std::sort()
一起使用。
然而,我并没有得到我想要的。我的期望是 Persons 首先按姓名排序,然后按年龄排序。但是我用两种解决方案得到了相同的结果:
che is less than xu
(wu, 30)
(che, 34)
(xu, 21)
我期望的顺序是:
(che, 34)
(wu, 30)
(xu, 21)
谁能帮我指出我犯的错误?谢谢
源代码为:
class Person{
public:
string _name;
int _age;
public:
Person(string name, int age):_name(name),_age(age){
}
bool operator<(const Person* b) const {
cout<<"Expect "<<_name <<b->_name <<" "<< (_name < b->_name)<<endl;
if(_name != b->_name) {
return _name < b->_name;
}
else return _age<b->_age;
}
bool operator<(const Person& b) const {
if(_name!=b._name) {
cout<<_name <<" is less than "<<b._name<<endl;
return _name<b._name;
} else return _age<b._age;
}
friend ostream& operator<<(ostream& out, const Person& b) {
out << "(" << b._name << ", " << b._age << ")"<<endl;
return out;
}
};
bool PersonCompare(const Person* a, const Person* b ){
cout<<"Expect "<<a->_name <<b->_name <<" "<< (a->_name < b->_name)<<endl;
if(a->_name != b->_name) {
return a->_name < b->_name;
}
else return a->_age<b->_age;
}
class PersonPrint{
public:
PersonPrint(){
}
void operator()(const Person& person){
cout<<person;
}
void operator()(const Person* person){
cout<<*person;
}
};
void testSort(){
vector<Person*> personsList;
personsList.push_back(new Person("xu", 12));
personsList.push_back(new Person("che", 23));
personsList.push_back(new Person("sxy", 34));
/*std::sort(personsList.begin(), personsList.end(), [](Person* a, Person* b ){
if(a->_name!=b->_name) return a->_name<b->_name;
else return a->_age<b->_age;
}); *///This works
/* std::sort(personsList.begin(), personsList.end(), PersonCompare ) *///This works..
std::sort(personsList.begin(), personsList.end()); //This does not work
for_each(personsList.begin(), personsList.end(), PersonPrint());
}
==============
是lambda/operator里面的逻辑错误。将if(a._name<b._name)
改为if(a._name!=b._name)
后,错误修复。
///////////////////////////////////
我更新了代码。
为classPerson
添加bool operator<(const Person* b) const{}
,然后尝试对Person*
的向量进行排序。但是结果并没有像我预期的那样排序,新添加的operator<(const Person*)
没有被调用。这里有什么建议吗?谢谢
您的比较功能正在涉足未定义行为的领域。毫不奇怪,您没有看到预期的结果。
来自 std::sort's documentation
comp - comparison function object (i.e. an object that satisfies the
requirements of Compare) which returns true if the first argument is
less than (i.e. is ordered before) the second.
Compare的要求:
The return value of the function call operation applied to an object
of type Compare, when contextually converted to bool, yields true if
the first argument of the call appears before the second in the strict
weak ordering relation induced by this Compare type, and false
otherwise.
您的比较功能不符合严格的周排序标准。
你可以简单地做:
std::sort(persons.begin(), persons.end(),
[](const Person& a, const Person& b) { return std::tie(a.name, a.age) < std::tie(b.name, b.age); })
我写了一篇关于这个的文章:https://isocpp.org/blog/2016/05/strict-weak-ordering-and-stl 你可以参考一下。
编辑(基于OP的编辑):
这不起作用,因为您已经为 Person
class 提供了成员函数,而您要调用的类型是 Person*
。两者是不同的类型。
您必须将 PrintPerson
函数的 定义 移到 class 之外,并使其 声明为 Person 中的友元方法 class。不幸的是,您不能对 bool operator<(Person *a, Person *b)
做同样的事情,因为运算符重载不适用于指针类型。您唯一的选择是传递一个比较器。
我正在尝试按 person.name 和年龄对人物向量进行排序。因此,我试图覆盖 Person
定义中的 operator<
,并将仿函数与 std::sort()
一起使用。
然而,我并没有得到我想要的。我的期望是 Persons 首先按姓名排序,然后按年龄排序。但是我用两种解决方案得到了相同的结果:
che is less than xu
(wu, 30)
(che, 34)
(xu, 21)
我期望的顺序是:
(che, 34)
(wu, 30)
(xu, 21)
谁能帮我指出我犯的错误?谢谢
源代码为:
class Person{
public:
string _name;
int _age;
public:
Person(string name, int age):_name(name),_age(age){
}
bool operator<(const Person* b) const {
cout<<"Expect "<<_name <<b->_name <<" "<< (_name < b->_name)<<endl;
if(_name != b->_name) {
return _name < b->_name;
}
else return _age<b->_age;
}
bool operator<(const Person& b) const {
if(_name!=b._name) {
cout<<_name <<" is less than "<<b._name<<endl;
return _name<b._name;
} else return _age<b._age;
}
friend ostream& operator<<(ostream& out, const Person& b) {
out << "(" << b._name << ", " << b._age << ")"<<endl;
return out;
}
};
bool PersonCompare(const Person* a, const Person* b ){
cout<<"Expect "<<a->_name <<b->_name <<" "<< (a->_name < b->_name)<<endl;
if(a->_name != b->_name) {
return a->_name < b->_name;
}
else return a->_age<b->_age;
}
class PersonPrint{
public:
PersonPrint(){
}
void operator()(const Person& person){
cout<<person;
}
void operator()(const Person* person){
cout<<*person;
}
};
void testSort(){
vector<Person*> personsList;
personsList.push_back(new Person("xu", 12));
personsList.push_back(new Person("che", 23));
personsList.push_back(new Person("sxy", 34));
/*std::sort(personsList.begin(), personsList.end(), [](Person* a, Person* b ){
if(a->_name!=b->_name) return a->_name<b->_name;
else return a->_age<b->_age;
}); *///This works
/* std::sort(personsList.begin(), personsList.end(), PersonCompare ) *///This works..
std::sort(personsList.begin(), personsList.end()); //This does not work
for_each(personsList.begin(), personsList.end(), PersonPrint());
}
==============
是lambda/operator里面的逻辑错误。将if(a._name<b._name)
改为if(a._name!=b._name)
后,错误修复。
///////////////////////////////////
我更新了代码。
为classPerson
添加bool operator<(const Person* b) const{}
,然后尝试对Person*
的向量进行排序。但是结果并没有像我预期的那样排序,新添加的operator<(const Person*)
没有被调用。这里有什么建议吗?谢谢
您的比较功能正在涉足未定义行为的领域。毫不奇怪,您没有看到预期的结果。 来自 std::sort's documentation
comp - comparison function object (i.e. an object that satisfies the requirements of Compare) which returns true if the first argument is less than (i.e. is ordered before) the second.
Compare的要求:
The return value of the function call operation applied to an object of type Compare, when contextually converted to bool, yields true if the first argument of the call appears before the second in the strict weak ordering relation induced by this Compare type, and false otherwise.
您的比较功能不符合严格的周排序标准。
你可以简单地做:
std::sort(persons.begin(), persons.end(),
[](const Person& a, const Person& b) { return std::tie(a.name, a.age) < std::tie(b.name, b.age); })
我写了一篇关于这个的文章:https://isocpp.org/blog/2016/05/strict-weak-ordering-and-stl 你可以参考一下。
编辑(基于OP的编辑):
这不起作用,因为您已经为 Person
class 提供了成员函数,而您要调用的类型是 Person*
。两者是不同的类型。
您必须将 PrintPerson
函数的 定义 移到 class 之外,并使其 声明为 Person 中的友元方法 class。不幸的是,您不能对 bool operator<(Person *a, Person *b)
做同样的事情,因为运算符重载不适用于指针类型。您唯一的选择是传递一个比较器。