类外运算符重载

发布于 2024-08-24 22:44:53 字数 577 浏览 6 评论 0 原文

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++ 中,哪种方法更正确?哪个更可取?

There are two ways to overload operators for a C++ class:

Inside class

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 ;
    }
} ;

Outside class

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 ;
}

(Apparently in C# you can only use the "outside class" method.)

In C++, which way is more correct? Which is preferable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

天气好吗我好吗 2024-08-31 22:44:53

基本问题是“您希望对运算符的左侧参数执行转换吗?”。如果是,请使用免费函数。如果不是,请使用班级成员。

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

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

执行转换以将 char * "foo"std::string 中。因此,我们将字符串的operator+() 变成了一个自由函数。

The basic question is "Do you want conversions to be performed on the left-hand side parameter of an operator?". If yes, use a free function. If no, use a class member.

For example, for operator+() for strings, we want conversions to be performed so we can say things like:

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

where a conversion is performed to turn the char * "foo" into an std::string. So, we make operator+() for strings into a free function.

素食主义者 2024-08-31 22:44:53

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


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

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 href="http://en.wikipedia.org/wiki/Barton-Nackman_trick" rel="noreferrer">Barton-Nackman 技巧,因为由于模板的怪癖和重载,可能找不到否则

First: the two different ways are really "overload as a member" and "overload as a non-member", and the latter has two different ways to write it (as-friend-inside class definition and outside class definition). Calling them "inside class" and "outside class" is going to confuse you.


Overloads for +=, +, -=, -, etc. have a special pattern:

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

This pattern allows the conversions mentioned in the other answers for the LHS argument while simplifying the implementation considerably. (Either member or non-member allows conversions for the RHS when it's passed either as a const& or by value, as it should be.) Of course, this only applies when you do actually want to overload both += and +, -= and -, etc., but that is still common.


Additionally, you sometimes want to declare your non-member op+, etc. as friends within the class definition using the Barton-Nackman trick, because due to quirks of templates and overloading, it may not be found otherwise.

樱花细雨 2024-08-31 22:44:53

Meyer 的《Effective C++》对此问题进行了精彩的讨论:第 24 项是“当类型转换应应用于所有参数时声明非成员函数”,第 46 项是“当需要类型转换时在模板内定义非成员函数”。

There is an excellent discussion of this issue in Meyer's Effective C++: Item 24 is "Declare non-member functions when type conversions should apply to all parameters" and Item 46 is "Define non-member functions inside templates when type conversions are desired".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文