问题
I remeber C++ Primer
tells us operator<
should be non-member function
, and I always obey the rule. But now I want to know the reason.
I wrote following code:
#include <iostream>
using std::cout;
using std::endl;
struct Point1
{
int x, y;
Point1(const int a, const int b): x(a), y(b) { }
};
inline bool operator<(const Point1& lhs, const Point1& rhs)
{
return lhs.x < rhs.x || (lhs.x == rhs.x && lhs.y < rhs.y);
}
struct Point2
{
int x, y;
Point2(const int a, const int b): x(a), y(b) { }
bool operator<(const Point2& rhs)
{
return x < rhs.x || (x == rhs.x && y < rhs.y);
}
};
int main()
{
Point1 a(1, 2), b(1, 3);
cout << (a < b) << " " << (b < a) << endl;
Point2 c(2, 3), d(2, 4);
cout << (c < d) << " " << (d < c) << endl;
}
In this case, It seems they don't make difference and member
function seems much simpler.
But in this case:
#include <iostream>
using std::cout;
using std::endl;
// Usually I write it for comparing floats
class Float1
{
long double _value;
public:
static const long double EPS = 1e-8;
Float1(const long double value): _value(value) { }
const long double Get() const { return _value; }
};
inline bool operator<(const Float1& lhs, const Float1& rhs)
{
return rhs.Get() - lhs.Get() > Float1::EPS;
}
inline bool operator<(const Float1& lhs, const long double rhs)
{
return rhs - lhs.Get() > Float1::EPS;
}
class Float2
{
long double _value;
public:
static const long double EPS = 1e-8;
Float2(const long double value): _value(value) { }
const long double Get() const { return _value; }
bool operator<(const Float2& rhs)
{
return rhs._value - _value > Float2::EPS;
}
bool operator<(const long double rhs)
{
return rhs - _value > Float2::EPS;
}
};
int main()
{
Float1 x(3.14);
Float2 y(2.17);
long double zero = .0;
cout << (x < zero) << " " << (zero < x) << endl;
//cout << (y < zero) << " " << (zero < y) << endl; Compile Error!
}
Both (x < zero) and (zero < x) work! (is long double
converted to Float
?)
But (zero < y) don't, because zero is not a Float
.
You see, in first case, member function
costs less code length, and in second case, non-member function
makes comparing easier. So I want to know
- In first case, should I use
member function
instead ofnon-member function
? - Why
C++ Primer
suggestsbinary operator
s benon-member function
? - Is there any other case that
member function
andnon-member function
make difference?
Thanks for helping!
回答1:
I think the basic answer is that non-member functions play better with implicit conversion. So if you can write your binary operator as a non-member function, you should.
回答2:
The question can be answered in different levels. In the highest level, from a design standpoint, operator<
is a binary operator. It is no more of an operation on the left hand side that it is on the right. Member functions, on the other hand are bound to the first argument, they are an operation on the first type.
From a technical point of view, and going right to the C++ language, this comes down to what you already noticed: member functions are not symmetric with respect to the types. That lack of symmetry means that an operator<
declared as a member function can only be applied when the left hand side is of the type that contains the member. No conversions can be applied before a member operator is called. On the other hand, because free functions are not more bound to the first argument than they are for the second, the free function operator<
will be picked up by ADL whenever any of the two arguments is of the appropriate type, allowing the same conversions to the first and second arguments.
回答3:
As a non-member the comparison operator works also for derived class (left hand side) arguments.
EDIT: and as @jonathan points out in a comment, it also allows value conversions, such as e.g. an int
left hand side argument.
If constructors and conversion operators are not explicit
, such conversions can allow meaningless and probably unintended code, e.g. comparing a T
instance to 5.
来源:https://stackoverflow.com/questions/12047174/why-should-operator-be-non-member-function