运算符在类外重载

时间:2010-03-11 14:51:30

标签: c++ operator-overloading

有两种方法可以为C ++类重载运算符:

内部课程

class Vector2
{
public:
    float x, y ;

    Vector2 operator+( const Vector2 & other )
    {
        Vector2 ans ;
        ans.x = x + other.x ;
        ans.y = y + other.y ;
        return ans ;
    }
} ;

课外

class Vector2
{
public:
    float x, y ;
} ;

Vector2 operator+( const Vector2& v1, const Vector2& v2 )
{
    Vector2 ans ;
    ans.x = v1.x + v2.x ;
    ans.y = v1.y + v2.y ;
    return ans ;
}

(显然在C#中你只能使用“外部类”方法。)

在C ++中,哪种方式更正确?哪个更好?

3 个答案:

答案 0 :(得分:49)

基本问题是“您是否希望在操作员的左侧参数上执行转换?”。如果是,请使用免费功能。如果不是,请使用班级成员。

例如,对于字符串的operator+(),我们希望执行转换,以便我们可以这样说:

string a = "bar";
string b = "foo" + a;

执行转化以将char * "foo"变为std::string。因此,我们将字符串operator+()变为自由函数。

答案 1 :(得分:16)

首先:两种不同的方式实际上是“作为成员重载”和“作为非成员重载”,而后者有两种不同的方式来编写它(as-friend-inside类定义和外部类定义) 。称他们为“课堂内”和“课堂外”会让你感到困惑。


+ =,+, - =, - 等的重载具有特殊模式:

struct Vector2 {
  float x, y;
  Vector2& operator+=(Vector2 const& other) {
    x += other.x;
    y += other.y;
    return *this;
  }
  Vector2& operator-=(Vector2 const& other) {
    x -= other.x;
    y -= other.y;
    return *this;
  }
};
Vector2 operator+(Vector2 a, Vector2 const& b) {
  // note 'a' is passed by value and thus copied
  a += b;
  return a;
}
Vector2 operator-(Vector2 a, Vector2 const& b) { return a -= b; } // compact

此模式允许LHS参数的其他答案中提到的转换,同时大大简化了实现。 (成员或非成员允许RHS以const&或按值传递时的转换。)当然,这仅适用于您实际上想要超载+ =和+, - =和 - 等,但这仍然很常见。


此外,您有时希望使用friends在类定义中将非成员op +等声明为Barton-Nackman trick,因为由于模板和重载的怪癖,可能找不到它otherwise

答案 2 :(得分:4)

在Meyer的Effective C ++中对这个问题进行了很好的讨论:第24项是“当类型转换应该应用于所有参数时声明非成员函数”,第46项是“当类型转换是在模板中定义非成员函数时所需的”。