gpt4 book ai didi

c++ - 为什么有些运算符只能作为成员函数重载,其他的作为友元函数重载,而其余的则两者都重载?

转载 作者:IT老高 更新时间:2023-10-28 14:00:03 26 4
gpt4 key购买 nike

为什么某些运算符只能作为成员函数重载,其他运算符作为非成员“自由”函数重载,而其余的则两者兼而有之?

这些背后的原理是什么?

如何记住哪些运算符可以重载为什么(成员、免费或两者)?

最佳答案

该问题列出了三类运算符。我认为,将它们放在一个列表中有助于理解为什么一些运算符被限制在它们可以重载的地方:

  • 必须作为成员重载的运算符。这些是相当少的:
  • 赋值 operator=() 。允许非成员分配似乎为运算符(operator)劫持分配打开了大门,例如,通过重载不同版本的 const 资格。鉴于赋值运算符相当基本,这似乎是不可取的。
  • 函数调用 operator()() 。函数调用和重载规则已经足够复杂了。通过允许非成员函数调用运算符来进一步复杂化规则似乎是不明智的。
  • 下标 operator[]() 。使用有趣的索引类型似乎会干扰对运算符的访问。尽管劫持重载的危险很小,但似乎没有太大的好处,但编写高度非显而易见的代码的潜力却很有趣。
  • 类成员访问 operator->() 。我看不出有任何将这个运算符重载为非成员的不良滥用行为。另一方面,我也看不到任何东西。此外,类成员访问运算符具有相当特殊的规则,并且玩弄干扰这些的潜在重载似乎是不必要的复杂化。

  • 尽管可以想象重载这些成员中的每一个都是非成员(尤其是在数组/指针上工作的下标运算符,并且它们可以在调用的任何一侧),但如果例如分配可能被劫持,这似乎令人惊讶通过非成员重载,这是比成员分配之一更好的匹配。这些运算符也相当不对称:您通常不希望在涉及这些运算符的表达式的两侧都支持转换。

    也就是说,例如,对于 lambda 表达式库,如果可以重载所有这些运算符会很好,我认为没有内在的技术原因来阻止这些运算符被重载。
  • 必须作为非成员函数重载的运算符。
  • 用户定义的文字 operator"" name()

  • 这个运算符有点奇怪,可以说并不是真正的运算符。在任何情况下,都没有对象可以调用可以为其定义成员的成员:用户定义文字的左参数始终是内置类型。
  • 问题中没有提到,但也有一些运算符根本不能重载:
  • 成员选择器 .
  • 指向成员对象访问运算符的指针 .*
  • 作用域运算符 ::
  • 三元运算符 ?:

  • 这四个运算符被认为太基础而根本无法干预。尽管有人提议允许在某个时候重载 operator.(),但并没有强烈支持这样做(主要用例是智能引用)。虽然肯定有一些可以想象的上下文,也可以重载这些运算符。
  • 可以作为成员或非成员重载的运算符。这是大部分的运营商:
  • 前后递增/递减 operator++() , operator--() , operator++(int) , operator--(int)
  • [unary] 解引用 operator*()
  • operator&()的[一元]地址
  • [一元] 符号 operator+() , operator-()
  • 逻辑否定 operator!() (或 operator not() )
  • 按位反转 operator~()(或 operator compl())
  • operator==()operator!=()operator<()operator>()operator<=()operator>() 的比较
  • [二进制] 算术 operator+() , operator-() , operator*() , operator/() , operator%()
  • [二进制] 按位 operator&()(或 operator bitand())、operator|()(或 operator bit_or())、operator^()(或 operator xor())
  • 按位移位 operator<<()operator>>()
  • 逻辑operator||()(或operator or())和operator&&()(或operator and())
  • 操作/赋值 operator@=()(因为 @ 是一个合适的运算符符号()
  • operator,() 序列(重载实际上杀死了序列属性!)
  • 指针指向成员访问 operator->*()
  • 内存管理 operator new()operator new[]()operator new[]()operator delete[]()

  • 可以作为成员或非成员重载的运算符对于基本对象维护来说不像其他运算符那样必要。这并不是说它们不重要。事实上,这个列表包含一些运算符,它们是否应该是可重载的(例如, operator&() 的地址或通常导致排序的运算符,即 operator,()operator||()operator&&()
    当然,C++ 标准并没有说明为什么事情会按照他们的方式完成(并且也没有早期做出这些决定的记录)。最好的理由可能可以在 Bjarne Stroustrup 的“C++ 的设计和进化”中找到。我记得在那里讨论过运营商,但似乎没有可用的电子版本。

    总的来说,除了潜在的并发症之外,我认为没有真正充分的理由限制这些限制,而这通常被认为不值得付出努力。然而,我怀疑这些限制可能会被取消,因为与现有软件的交互必然会以不可预测的方式改变某些程序的含义。

    关于c++ - 为什么有些运算符只能作为成员函数重载,其他的作为友元函数重载,而其余的则两者都重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1132600/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com