为什么运营商<是非会员功能?

时间:2012-08-21 00:58:16

标签: c++ operator-overloading

我记得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 <零)和(零long double转换为Float?)

但是(零&lt; y)不,因为零不是Float

您会看到,在第一种情况下,member function的代码长度会减少,而在第二种情况下,non-member function会使比较更容易。所以我想知道

  • 在第一种情况下,我应该使用member function代替non-member function吗?
  • 为什么C++ Primer建议binary operatornon-member function
  • 是否有其他案例member functionnon-member function有所不同?

感谢您的帮助!

3 个答案:

答案 0 :(得分:5)

我认为基本的答案是非成员函数在隐式转换时表现更好。因此,如果您可以将二元运算符编写为非成员函数,则应该。

答案 1 :(得分:3)

这个问题可以在不同层面回答。在最高级别,从设计角度来看,operator<是二元运算符。左侧的操作不再是右侧的操作。另一方面,成员函数绑定到第一个参数,它们是 on 的第一个类型。

从技术角度来看,直接使用C ++语言,这归结为您已经注意到的内容:成员函数在类型方面不对称。缺乏对称意味着声明为成员函数的operator<只能在包含该成员的类型的左侧 时应用。在调用成员运算符之前,不能应用任何转换。另一方面,因为自由函数不是第一个参数的约束而不是第二个参数,所以每当任何两个参数时,ADL就会选择自由函数operator<。是适当的类型,允许相同的转换为第一个和第二个参数。

答案 2 :(得分:2)

作为非成员,比较运算符也适用于派生类(左侧)参数。


编辑:并且正如@jonathan在评论中指出的那样,它还允许值转换,例如一个int左手边的论点。

如果构造函数和转换运算符不是explicit,则此类转换可能允许无意义且可能无意义的代码,例如将T实例与5进行比较。