简体   繁体   English

为什么重载复合赋值运算符可以是非成员函数?

[英]Why can overloaded compound assignment operators be non-member functions?

I've just discovered recently that compound assignment operators (such as operator+= or operator-= ) can be overloaded outside class scope. 我刚刚发现复合赋值运算符(例如operator+=operator-= )可以在类范围之外重载。

Consider: 考虑:

class X { }; // A third party class

// The following function is legal:
X& operator+=(X& lhs, const X& rhs) {
    // ...
}

Obviously, the non-member function can't touch the private interface of X , so there's no encapsulation concern here. 显然,非成员函数不能触及X的私有接口,因此这里没有封装问题。 But it does make it seem as if it's part of X 's own interface, which it clearly isn't. 但它确实使它看起来好像它是X自己界面的一部分,显然它不是。

It seems to me this can lead to some serious code abuse and confusing behavior. 在我看来,这可能导致一些严重的代码滥用和混乱的行为。 Imagine someone thought it would be nice to use it for some "clever hacks" with standard contains such as std::vector or std::map . 想象一下,有人认为将它用于标准包含的一些“聪明的黑客”会更好,例如std::vectorstd::map

This is especially peculiar since other operators such as operator[] and operator-> can't be non-member functions for what I thought was this very reason. 这是特别奇怪的,因为其他运算符如operator[]operator->不能成为我认为是这个原因的非成员函数。

So why is it allowed? 那么为什么允许呢?

So why is it allowed? 那么为什么允许呢?

You are asking us to read the mind of Stroustrop. 你要求我们阅读Stroustrop的思想。 Not possible. 不可能。
But a general principle of C++ is not to limit developers (we don't provide a neutered set of tools that are safe to play with. We provide the full set of razor saws and spinning flails). 但是C ++的一般原则并不是限制开发人员(我们不提供一套可以安全使用的绝对工具。我们提供全套剃刀锯和旋转连枷)。

It seems to me this can lead to some serious code abuse and confusing behavior. 在我看来,这可能导致一些严重的代码滥用和混乱的行为。 Imagine someone thought it would be nice to use it for some "clever hacks" with standard contains such as std::vector or std::map. 想象一下,有人认为将它用于标准包含的一些“聪明的黑客”会更好,例如std :: vector或std :: map。

Yes it can. 是的,它可以。
When you abuse operator overloading it can lead to some dangerous and deadly things. 当你滥用运算符重载时,它可能导致一些危险和致命的事情。 Best not to do it (especially for other peoples or standard classes). 最好不要这样做(特别是对其他人或标准班)。

But it can provide some potentially useful situation (when you are careful). 但它可以提供一些潜在的有用情况(当你小心的时候)。 This is particularly useful when you are building a numeric "type" class as it helps with auto conversions which make the code more natural to read. 这在构建数字“类型”类时特别有用,因为它有助于自动转换,使代码更自然。

Consider if library A defines an object (let's say a Matrix object). 考虑库A是否定义了一个对象(比如说一个Matrix对象)。 Library B extends library A with some similar object (let's say Vectors). 库B扩展了库A,其中包含一些类似的对象(比如说Vector)。

Library B wants to define operators which link matrices to vectors (eg multiply). 库B想要定义将矩阵链接到向量的运算符(例如,乘法)。 But if defining these operator overloads had to be done within the original object, the writers would be stuck, and users would be left in the strange situation where they can do vector * matrix, but not matrix * vector. 但是如果定义这些运算符重载必须在原始对象中完成,则编写器将被卡住,并且用户将处于奇怪的情况,他们可以执行向量*矩阵,但不能执行矩阵*向量。

To look specifically at += and -= as you mention, consider a 1-by-n matrix, which is essentially a vector. 如你所述,特别注意+ =和 - =,考虑1乘n矩阵,它本质上是一个向量。 We now want to be able to perform matrix += vector. 我们现在希望能够执行矩阵+ =向量。

Allowing them to be defined externally avoids this problem. 允许在外部定义它们可以避免此问题。

It seems to me this can lead to some serious code abuse and confusing behavior 在我看来,这可能导致一些严重的代码滥用和混乱的行为

Quite right. 非常正确。 But don't forget this is a language which has a built-in preprocessor. 但是不要忘记这是一种内置预处理器的语言。 If other developers want to confuse you, they already have much more powerful tools available. 如果其他开发人员想让您感到困惑,他们已经拥有了更强大的工具。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM