C++ 操作符在类外重载

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2425906/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:27:01  来源:igfitidea点击:

Operator overloading outside class

c++operator-overloading

提问by bobobobo

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

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

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.)

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

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

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

回答by

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:

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

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.

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

回答by bobobobo

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.

第一:两种不同的方式实际上是“作为成员重载”和“作为非成员重载”,后者有两种不同的写法(as-friend-inside class definition and outside class definition)。称他们为“班内”和“班外”会让你感到困惑。



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.

这种模式允许 LHS 参数的其他答案中提到的转换,同时大大简化了实现。(当 RHS 以 aconst&或按值传递时,成员或非成员都允许对 RHS 进行转换,这应该是。)当然,这仅适用于您确实想要重载 += 和 +、-= 和- 等,但这仍然很常见。



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

此外,你有时要声明的非成员运算+等作为朋友使用类定义中巴顿Nackman诀窍,因为由于模板和重载怪癖,它可能不会被发现,否则

回答by Francesco

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".

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