Problem overloading the < operator in C++
I have a vector of Student objects which I want to sort using #include <algorithm>
and sort(list.begin(), list.end());
In order to do this, I understand that I need to overload the "<" operator but after trying (and failing) with several methods suggested online, I am running out of ideas.
Here is my latest attempt:
In Student.h...
...
using namespace std;
class Student
{
friend bool operator <(const Student& first, const Student& second);
public:
...
private:
...
};
开发者_运维技巧
And in Student.cpp...
...
#include "Student.h"
using namespace std;
...
bool operator <(const Student& first, const Student& second)
{
return first.Name() < second.Name();
}
where "Name()" is a constant function which returns a string.
The program compiles and runs, but my operator function is never called during the sort and when I tried comparing two Student objects like s1 < s2
I got an "error: overloaded operator not found"
How can I correctly overload this operator so that my sort will work as I intend?
You didn't say which compiler you were using, but I suspect you're using a fairly recent one that implements the "friend is not a declaration" rule. The friend statement inside the class doesn't serve as a function declaration; other modules that include Student.h don't see any declaration of the function. It's visible only inside the Student.cpp file. (Older compilers don't have this rule, and treat a friend declaration as a function declaration.)
The function doesn't need to be a friend, since it doesn't use any private members of the Student class (I'm assuming Name() is public). Move the function declaration outside the class, and replace "friend" with "extern", and it should work.
It is possible to make the operator a member function, as some posters above suggested, but it isn't necessary. Making comparison operators member functions is generally frowned upon, because it means that the two arguments aren't treated symmetrically (one is the invisible "this" argument, the other is a normal function argument), which can lead to surprising results in some cases (for example, different type conversions may be applied to the arguments).
I wouldn't use a friend here, and I'm not sure it works at all. What I would use is...
class Student
{
public:
bool operator< (const Student& second) const;
};
bool Student::operator< (const Student& second) const
{
return (Name() < second.Name());
}
Note the trailing const, indicating that within operator<, *this is constant.
EDIT I cannot delete this answer because it was accepted, but I would if I could. I also can't replace it with a correct one. See Drew Dormanns comment below, and Ross Smiths answer.
By the way, with a function this simple I would personally just do this, unless the style guide bans the definition of functions inside class definitions:
class Student
{
friend bool operator <(const Student& first, const Student& second)
{
return first.Name() < second.Name();
}
...
};
This form of the "friend" declaration lets you define a non-member operator<
inside the body of the class. It's still a friend, so Name()
can be private if desired.
Well, you could do it as an internal operator:
class Student
{
public:
bool operator <(const Student& second) const;
...
private:
...
};
With an implementation comparing 'this' to second. The question in my mind is: Does the 'Name' method come in a const flavor? Because if it doesn't, then you can't write a const method that uses it.
精彩评论