如何为类重载operator +()

时间:2011-09-29 05:58:51

标签: c++ operator-overloading

以下是包含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;
   }

7 个答案:

答案 0 :(得分:3)

声明一个函数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的成员进行操作,而不是临时对象。返回时,返回对此的引用。

答案 1 :(得分:1)

不应该是:

 feetInches temp = *this; 

答案 2 :(得分:0)

temp feetInches是您从添加中返回的对象。这是结果。

答案 3 :(得分:0)

operator +必须返回一个新对象。临时对象是这个新对象。

答案 4 :(得分:0)

注意这是一个const函数。其成员无法修改。因此,临时对象用于保存结果。

答案 5 :(得分:0)

C ++中operator +的语义是将2个对象一起添加并返回一个全新的结果,而无需修改要添加的任何对象。额外的temp实例就是全新的结果。

答案 6 :(得分:0)

您正在实现二进制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 + objobj + 1将同时使用该单个实现,在成员函数方法中,编译器无法解析1 + obj,因为在调用之前它无法转换第一个元素会员职能
  • 效率:按值取第一个参数意味着可以优化用作第一个参数的临时值。

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

有关运算符重载的更多信息here

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