我记得C++ Primer
告诉我们operator<
应该是non-member function
,而且我始终遵守这条规则。但现在我想知道原因。
我写了以下代码:
#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;
}
在这种情况下,似乎它们没有区别,member
功能似乎更简单。
但在这种情况下:
#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!
}
(x <零)和(零Float
?)
但是(零&lt; y)不,因为零不是Float
。
您会看到,在第一种情况下,member function
的代码长度会减少,而在第二种情况下,non-member function
会使比较更容易。所以我想知道
member function
代替non-member function
吗?C++ Primer
建议binary operator
为non-member function
?member function
和non-member function
有所不同?感谢您的帮助!
答案 0 :(得分:5)
我认为基本的答案是非成员函数在隐式转换时表现更好。因此,如果您可以将二元运算符编写为非成员函数,则应该。
答案 1 :(得分:3)
这个问题可以在不同层面回答。在最高级别,从设计角度来看,operator<
是二元运算符。左侧的操作不再是右侧的操作。另一方面,成员函数绑定到第一个参数,它们是 on 的第一个类型。
从技术角度来看,直接使用C ++语言,这归结为您已经注意到的内容:成员函数在类型方面不对称。缺乏对称意味着声明为成员函数的operator<
只能在包含该成员的类型的左侧 时应用。在调用成员运算符之前,不能应用任何转换。另一方面,因为自由函数不是第一个参数的约束而不是第二个参数,所以每当任何两个参数时,ADL就会选择自由函数operator<
。是适当的类型,允许相同的转换为第一个和第二个参数。
答案 2 :(得分:2)
作为非成员,比较运算符也适用于派生类(左侧)参数。
编辑:并且正如@jonathan在评论中指出的那样,它还允许值转换,例如一个int
左手边的论点。
如果构造函数和转换运算符不是explicit
,则此类转换可能允许无意义且可能无意义的代码,例如将T
实例与5进行比较。