如何重载类的operator +()

How to overload operator +() for a class

本文关键字:operator 重载 何重载      更新时间:2023-10-16

下面是一个包含operator+方法的类。我理解它的feetInches::operator+(const feetInches &other) const部分但在方法定义中,为什么有一个额外的feetInches,它在这里代表什么?

   class feetInches {
      public:
         feetInches(int inFeet = 0, int inInches = 0);
         feetInches operator+(const feetInches &other) const;
         void print() const;
      private:
         int feet;
         int inches;
   };
   feetInches feetInches::operator+(const feetInches &other) const    
   {
      feetInches temp;
      temp.feet = feet + other.feet;
      temp.inches = inches + other.inches;
      return temp;
   }

声明一个函数const意味着您不能修改这个对象(当然,除非您尝试修改mutable字段,但那是另一回事)。因此,要返回两个feetInches的和,必须创建一个新的feetInches对象并返回它。

// return type     scope resolution             parameter type
//      |                 |                           |
//      |                 |                           |
    feetInches        feetInches::operator+(const feetInches &other) const    
    {
//      return value - you can't modify this (because method is const), so you must create 
//           |       a third object
        feetInches temp;
        temp.feet = feet + other.feet;
        temp.inches = inches + other.inches;
        return temp;
    }
编辑:

作为比较,考虑重载操作符+=:
 feetInches& feetInches::operator+=(const feetInches &other) 
 {
    feet = feet + other.feet;
    inches = inches + other.inches;
    return *this;
 }

因为在这种情况下this对象被改变了,操作符不再是常量。您还可以操作this的成员,而不是临时对象。返回时,返回this的引用

应该是:

 feetInches temp = *this; 

temp feetInches是您从加法返回的对象。

操作符+必须返回一个新对象。这个临时对象就是这个新对象。

注意这是一个const函数。它的成员不能被修改。因此,使用一个临时对象来保存结果。

操作符+在c++中的语义是将两个对象加在一起并返回一个全新的结果,而不修改添加的任何一个对象。额外的temp实例是全新的结果。

您正在实现二进制operator+,其定义接受两个元素(未修改),并使用相加的结果生成第三个元素。代码中额外的feetInches对象的原因是您不想修改左侧的对象。对于操作符的理解,如果考虑以下实现,可能会更简单:

feetInches operator+( feetInches const & other ) const {
   return feetInches( feet+other.feet, inches+other.inches );
}

原始代码只是将单个语句拆分为4个不同的语句:对象的构造(必须是稍后使用的命名变量),设置两个字段,并返回对象。

或者,操作符重载的推荐方法略有不同:
class feetInches {
   int feet, inches;
public:
   feetInches( int feet = 0, int inches = 0 ) 
      : feet(feet), inches(inches) {}
   // Implement += internally [*]
   feetInches& operator+=( feetInches const & rhs ) {
      feet += rhs.feet;
      inches += rhs.inches;
      return *this;
   }
};
// Implement + as a free function taking the first element by value:
feetInches operator+( feetInches lhs, feetInches const & rhs ) {
   lhs += rhs;       // Reuse += implementation, no need to repeat
   return lhs;
}

至于原因:

  • 灵活性:允许operator+operator+=与单一实现
  • 类型对称:允许编译器在两个操作数中执行隐式转换
    • 1 + obj, obj + 1都将与单个实现一起工作,在成员函数方法中,1 + obj不能被编译器解析,因为它不能在调用成员函数
    • 之前转换第一个元素。
  • 效率:按值获取第一个参数意味着作为第一个参数的临时变量可以被优化掉。

注意,在修改后的版本中仍然有三个对象:原始的左侧,作为operator+的第一个参数的副本被返回,右侧,我们没有删除对象。此外,这种特殊类型的实现需要在operator+返回语句中进行额外的复制(不能省略从参数到返回值的复制),但是对于可以移动的更复杂类型,返回语句将移动对象的内容。

这里有更多关于操作符重载的信息

[*]这是一个设计决策,operator+=可以作为一个自由函数实现,但它可以被认为(至少我这样做),语义上+=是第一个参数的操作。