The following is a class that contains a operator+
method. I understand the feetInches::operator+(const feetInches &other) const
part of it but in the method definition, why is there an extra feetInches
and what does it represent here?
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开发者_JS百科+(const feetInches &other) const
{
feetInches temp;
temp.feet = feet + other.feet;
temp.inches = inches + other.inches;
return temp;
}
Declaring a function const
means you can't modify the this object (unless of course you try to modify mutable
fields, but that's a different story). Therefore, to return something which is the sum of two feetInches
, you must create a new feetInches
object and return that.
// 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;
}
EDIT:
As a comparison, consider overloading operator +=
:
feetInches& feetInches::operator+=(const feetInches &other)
{
feet = feet + other.feet;
inches = inches + other.inches;
return *this;
}
Because in this case the this
object is changed, the operator is no longer constant. You also operate on members of this
, not a temporary object. On return, you return a reference to this.
shouldn't it be:
feetInches temp = *this;
The temp
feetInches
is the object you return from the addition. It's the result.
The operator + must return a new object. The temp object is this new object.
Note this is a const function. Its members can't modified. Therefore a temp object is used to hold the result.
The semantics of an operator+ in C++ are to add 2 objects together and return a brand new result, without modifying either of the objects you are adding. The extra temp
instance is that brand new result.
You are implementing binary operator+
, the definition of which takes two elements (untouched) and generates a third element with the result of the addition. The reason for the extra feetInches
object in the code is that you don't want to modify the left hand side object. As of understanding the operator, maybe it could be simpler if you considered the implementation:
feetInches operator+( feetInches const & other ) const {
return feetInches( feet+other.feet, inches+other.inches );
}
The original code just splits that single statement into 4 different statements: construction of the object (must be a named variable to be used later), setting the two fields, and returning the object.
Alternatively, the recommended approach to operator overloading would be slightly different:
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;
}
As of the reasons:
- Flexibility: Allows for
operator+
andoperator+=
with a single implementation - Type symmetry: Allows the compiler to perform implicit conversions in both operands
1 + obj
,obj + 1
will both work with that single implementation, in the member function approach,1 + obj
cannot be resolved by the compiler, as it cannot convert the first element before calling the member function
- Efficiency: Taking the first argument by value means that temporaries used as first argument can be optimized away.
Note that in the modified version there are still three objects: the original left hand side, the copy as first argument of operator+
that gets returned and the right hand side, we have not removed the object. Also, this implementation for this particular type requires an extra copy in the operator+
return statement (the copy from the argument to the return value cannot be elided), but for more complex types that can be moved, the return statement will move the contents of the object.
More on operator overloading here
[*] This is a design decision, operator+=
can be implemented as a free function, but it can be argued (at least I do) that semantically +=
is an operation of the first argument.
精彩评论