C++开发初级


861 浏览 5 years, 3 months

10.2 重载算术运算符

版权声明: 转载请注明出处 http://www.codingsoho.com/

重载算术运算符

现在您已经理解了如何编写operator+,剩余的基本算术运算符就变得简单了。下面是-、*以及/的声明(还可以重载%,但这对于存储在SpreadsheetCell中的double值而言没有意义)。

class SpreadsheetCell
{
 public:
  friend const SpreadsheetCell operator+(const SpreadsheetCell& lhs,
                     const SpreadsheetCell& rhs);
  friend const SpreadsheetCell operator-(const SpreadsheetCell& lhs,
                     const SpreadsheetCell& rhs);
  friend const SpreadsheetCell operator*(const SpreadsheetCell& lhs,
                     const SpreadsheetCell& rhs);
  friend const SpreadsheetCell operator/(const SpreadsheetCell& lhs,
                     const SpreadsheetCell& rhs);
};

代码取自 OperatorOverloading\SpreadsheetCell.h

下面是实现。唯一需要注意的是除0。如果发现除0,这个实现会抛出一个异常。

const SpreadsheetCell operator-(const SpreadsheetCell& lhs,
                const SpreadsheetCell& rhs)
{
  SpreadsheetCell newCell;
  newCell.set(lhs.mValue - rhs.mValue); // call set to update mValue and mString
  return newCell;
}

const SpreadsheetCell operator*(const SpreadsheetCell& lhs,
                const SpreadsheetCell& rhs)
{
  SpreadsheetCell newCell;
  newCell.set(lhs.mValue * rhs.mValue); // call set to update mValue and mString
  return newCell;
}

const SpreadsheetCell operator/(const SpreadsheetCell& lhs,
                const SpreadsheetCell& rhs)
{
  if (rhs.mValue == 0)
    throw invalid_argument("Divide by zero.");
  SpreadsheetCell newCell;
  newCell.set(lhs.mValue / rhs.mValue); // call set to update mValue and mString
  return newCell;
}

代码取自 OperatorOverloading\SpreadsheetCell.cpp

C++并没有要求在operator*中真正实现乘法,在operator/中实现除法。您可以在operator/中实现乘法,在operator+中实现除法,依此类推。然而这样做会让人非常迷惑,因此没有理由这么去做,除非是开玩笑。在可能的情况下,在实现中还是应该使用常用的运算符含义。

在C++中,无法改变运算符的优先级。例如,*以及/总是在+以及-之前求值。用户定义的运算符唯一能做的就是在运算符优先级已经确定的情况下编写实现.

重载简写算术运算符

除基本算术运算符之外,C++还提供了简写运算符,例如+=以及-=。您或许认为编写类的operator+时也就提供了operator+=。不是这么简单,您必须显式重载简写算术运算符(Arithmetic Shorthand Operators)。这些运算符与基本算术运算符不同,它们会改变运算符左边的对象,而不是创建一个新对象。此外还有一个微妙的差别,它们生成的结果是被修改对象的引用,这一点与赋值运算符类似。

简写算术运算符左边总是要有一个对象,因此应该将其作为方法,而不是全局函数。下面是SpreadsheetCell类的声明:

class SpreadsheetCell
{
 public:
  SpreadsheetCell& operator+=(const SpreadsheetCell& rhs);
  SpreadsheetCell& operator-=(const SpreadsheetCell& rhs);
  SpreadsheetCell& operator*=(const SpreadsheetCell& rhs);
  SpreadsheetCell& operator/=(const SpreadsheetCell& rhs);
};

代码取自 OperatorOverloading\SpreadsheetCell.h

下面是实现:

SpreadsheetCell& SpreadsheetCell::operator+=(const SpreadsheetCell& rhs)
{
  set(mValue + rhs.mValue); // call set to update mValue and mString
  return *this;
}

SpreadsheetCell& SpreadsheetCell::operator-=(const SpreadsheetCell& rhs)
{
  set(mValue - rhs.mValue); // call set to update mValue and mString
  return *this;
}

SpreadsheetCell& SpreadsheetCell::operator*=(const SpreadsheetCell& rhs)
{
  set(mValue * rhs.mValue); // call set to update mValue and mString
  return *this;
}

SpreadsheetCell& SpreadsheetCell::operator/=(const SpreadsheetCell& rhs)
{
  if (rhs.mValue == 0)
    throw invalid_argument("Divide by zero.");
  set(mValue / rhs.mValue); // call set to update mValue and mString
  return *this;
}

代码取自 OperatorOverloading\SpreadsheetCell.cpp

简写算术运算符是基本算术运算符以及赋值运算符的结合。根据上面的定义,可以编写如下的代码:

  SpreadsheetCell myCell(4), aThirdCell(2);
  aThirdCell -= myCell;
  aThirdCell += 5.4;

代码取自 OperatorOverloading\SpreadsheetCellTest.cpp

然而不能编写这样的代码(这是好事一桩!)

5.4 += aThirdCell;