【问题标题】:C++ -- How to overload operator+=?C++——如何重载运算符+=?
【发布时间】:2011-01-03 03:55:03
【问题描述】:

给定以下代码sn-p,

class Num
{
public:
    Num(int iNumber = 0) : m_iNumber(iNumber) {}

    Num operator+=(const Num& rhs)
    {
        this->m_iNumber = (this->m_iNumber + rhs.m_iNumber);
        return *this;
    }
private:
    int m_iNumber;
};

//===========================================================
int _tmain(int argc, _TCHAR* argv[])
{
    Num a(10);

    Num b(100);

    b += a;

    return 0;
}

我想知道如何正确重载operator+=

问题:

  1. 如何定义这个算子的签名?具体来说,返回值应该用什么?

  2. 函数体如何实现?

  3. 如何使用这个重载运算符?

我已经提供了上述解决方案,但我担心它不正确。

【问题讨论】:

  • @James,我通过谷歌搜索并没有找到一个好的资源来告诉我如何实现 operator+=。另外,我看到有些人使用“引用”作为这个函数的返回值,但我不知道为什么以及它的用途是什么。 ——谢谢
  • 一本不错的 C++ 书籍会告诉你如何去做。有时“通过谷歌搜索”是不够的;这当然不可靠。 :)
  • @q0987 - 作为旁注,我认为值得一提的是,如果您已经为您的班级实现了operator+=,那么将operator+ 实现为通常是一个好习惯好吧,就operator+= 而言。请参阅 Scott Meyers 所著的《更有效的 C++(第 1 版)》中的第 22 项。

标签: c++


【解决方案1】:

通过引用返回会更好

Num& operator+=(const Num& rhs){

      this->m_iNumber += rhs.m_iNumber;
      return *this;
}

【讨论】:

  • 您好 Prasoon,通过引用返回有什么好处,您如何使用它?我假设“通过引用返回”允许用户更改内部数据。谢谢
  • @q0987:任何赋值的结果通常返回赋值中最左边的变量。如果你返回一个参考,那就是你实际上在做的事情。如果您返回一个值,您将返回最左边赋值的 copy 而不是实际值。也就是说,Num a(10); (a += Num(10)) = 100; 导致 a 具有内容 20 而不是某些程序员可能期望的 100
  • @q0987 :此外,通过引用返回不会创建对象的副本(按值返回),因此不会调用副本 c-tor。然而,现代编译器在大多数情况下会省略副本。了解 RVO(返回值优化)。
  • 如果您不通过引用返回,则调用复制构造函数、临时副本等。通过引用返回不会允许用户修改您不允许通过访问器修改的内部数据.
  • 为什么返回类型不能为空?该函数不应该只为类的当前实例中的属性分配一个值吗......?为什么我们需要返回一个指向实例的指针?如果是这样,为什么是指针而不是对象本身?编辑:我想我明白了....在正常的演讲中:就像'+'运算符返回两者的总和一样,'+='应该两者:分配给左操作数并返回它改变的值;也就是说,最左边的值......如果有人认为他可以添加任何相关的东西,请做
【解决方案2】:

如果您关注this Wikibook,您将通过示例找到这些答案:

  1. Type& operator+=(const Type& right) 是正确的签名。
  2. 你做对了。
  3. 您可以像使用普通运算符一样使用重载运算符,只是您的类型已就位。这就是练习的重点。 ;)

请注意,复合赋值运算符必须是成员函数。

【讨论】:

  • 我不知道“复合赋值运算符必须是成员函数”——谢谢您的指出。
  • 嗯,在大多数情况下,操作员需要详细了解类的内部结构。根据定义,这几乎要求它是一个成员函数。
  • 其实复合赋值运算符可以是非成员函数。这在由于某种原因无法提供成员函数的情况下很有用。例如枚举(这是我遇到这个时正在搜索的内容)。在此处查看有关重载的有用讨论 (stackoverflow.com/questions/4421706/operator-overloading/…)
【解决方案3】:

任何赋值运算符(您最喜欢的运算符@的运算符=或运算符@=)的签名应该是

Class& operator @= (const Class& rhs);

也就是说,该函数通过 const 引用获取其参数(因为它不修改它),然后返回对该对象的可变引用。您返回非常量引用的原因是,由于历史原因,您可以编写如下代码:

(a += b) += c;

这绝不是好的风格,但它适用于整数,所以你应该努力让它也适用于你的类型。

至于你的函数体,你所拥有的完全正确。不过,一般来说,即使参数是接收器对象,您也应该确保代码可以正常工作。例如,如果你写类似

a += a;

这被翻译成

a.operator+= (a);

因此代码将在参数和接收器是同一个对象的情况下运行。复合赋值运算符通常不会出现这种情况(通常只有 operator= 需要担心这一点),但在某些情况下,如果您不小心,可能会被烧毁。

最后,您可以像在上面的示例代码中一样使用这个operator += 函数。任何使用+= 都会自动调用它。

希望这会有所帮助!

【讨论】:

  • 迂腐,挑剔,但我们通常更喜欢 '@' 而不是 '#' 用于任意运算符,以避免在语法荧光笔中触发'注释模式'。 :)
  • @Tomalak Geret'kal- 感谢您告诉我!我一定会在未来解决这个问题。
【解决方案4】:

您的示例完全正确:http://codepad.org/PVhQw9sc

  1. 您可以将返回值定义为您想要的任何值。如果您希望它与 int 匹配,则需要返回类型 Num&,并返回值 *this
  2. 你做得对。
  3. 你也做得对。

【讨论】:

  • 您好,Billy,我的 cmets 与我给 @Prasoon 的类似。例如,对于 INT,如何使用 += 链接或为 operator+= 的返回值分配新值?谢谢
  • @w0987:在那里回答了你的问题 :)
【解决方案5】:

像你一样写下身体。像您一样使用运算符。运算符应返回一个引用以允许链接。

here

【讨论】:

    【解决方案6】:

    你的算子函数也可以写成

    Num& operator += (const Num& rhs)
    {
       m_iNumber += rhs.m_iNumber;
       return m_iNumber;
    }
    

    *this->m_iNumberm_iNumber 在成员函数中本身是相同的,在我看来,使用前一种格式更容易打字。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-19
      • 1970-01-01
      • 2016-04-08
      • 2012-06-02
      • 2014-01-14
      • 2013-03-23
      • 2013-12-03
      相关资源
      最近更新 更多