2
#include <iostream>
using namespace std;

class Point {
private:
   int x, y; // Private data members

public:
   Point(int x = 0, int y = 0); // Constructor
   int getX() const; // Getters
   int getY() const;
   void setX(int x); // Setters
   void setY(int y);
   void print() const;
   const Point operator+(const Point & rhs);
         // Overload '+' operator as member function of the class
};

int main(int argc, char** argv)
{
    Point p1(1, 2), p2(4, 5);
   // Use overloaded operator +
   Point p3 = p1 + p2;
   p1.print();  // (1,2)
   p2.print();  // (4,5)
   p3.print();  // (5,7)

   // Invoke via usual dot syntax, same as p1+p2
   Point p4 = p1.operator+(p2);
   p4.print();  // (5,7)

   // Chaining
   Point p5 = p1 + p2 + p3 + p4;
   p5.print();  // (15,21)


    return 0;
}

// Constructor - The default values are specified in the declaration
Point::Point(int x, int y) : x(x), y(y) { } // Using initializer list

// Getters
int Point::getX() const { return x; }
int Point::getY() const { return y; }



// Setters
void Point::setX(int x) { this->x

= x;  }   // (*this).x = x; x = x
void Point::setY(int y) { this->y = y; }

// Public Functions
void Point::print() const {
   cout << "(" << x << "," << y << ")" << endl;
}

// Member function overloading '+' operator
const Point Point::operator+(const Point & rhs) {
   return Point(x + rhs.x, y + rhs.y);
}

I'm studying operator overloading and I don't understand why I get the error.

error: no match for 'operator+' (operand types are 'const Point' and 'Point')

I deleted const qualifier at the end of the operator+ function on purpose in order to understand it. Can someone explain explicitly why I need it?

askque
  • 319
  • 2
  • 9
  • In addition to the member function constness requirement for function chaining, also see: http://stackoverflow.com/questions/21890302/chaining-operation-and-order-of-evaluation-on-the-same-object - for a related chaining gotcha (just so you don't go on another 2-hour headscratcher) ;) – Fox Oct 27 '15 at 09:26

4 Answers4

2

The member

const Point Point::operator+(const Point & rhs);

is a non-const member, i.e. requires the lhs of the operation to be mutable, but (as the error message shows) you require an operation with a const lhs. Hence, you must declare the operator as such

Point Point::operator+(const Point & rhs) const;

Note that I also removed the const for the return type, as it is deprecated.


Why do you need the const? The natural + operator (for example between arithmetic types) does not alter its arguments and, as a consequence, the usual (human) conventions for using this operator implicitly assume that the arguments are not altered. In your particular case, the return of a+b was explicitly const (though that is deprecated AFAIK), so that in a+b+c = (a+b)+c the lhs is const and your non-const member function cannot be used.

Moreover, whenever a member function does not alter the state of its object, it should be declared const, so that it can be called for const object.


Alternatively, this operator can be defined as non-member function friend

Point operator+(const Point&lhs, const Point&rhs);

which more clearly expresses the symmetry between lhs and rhs (the corresponding function for your non-const member would have been

Point operator+(Point&lhs, const Point&rhs);

).

Walter
  • 44,150
  • 20
  • 113
  • 196
  • The `const` in return type *has* effects (as forbid `(a + b) = c`), but it is deprecated and disallow some optimization. – Jarod42 Oct 27 '15 at 08:42
  • "i.e. requires the lhs of the operation to be a lvalue" - This is wrong, it requires the lhs to be *mutable*, but it's fine if it's an rvalue. – Sebastian Redl Oct 27 '15 at 08:58
1

You need to define your method as a constone, i.e.:

const Point operator+(const Point & rhs) const;

p1+p2 returns a const Point so you need a const Point + const Point operator to be able to compute (p1+p2)+p3.

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
1

Good answers, but they don't explain why the const is an issue. The simple reason is chaining order and operator type matching.

Point p5 = p1 + p2 + p3 + p4;
// is interpreted as:
Point p5 = ConstPoint( (Point(p1)).operator+((const Point&)(p2)) + p3 + p4;
// as operator+ is left-to-right , not right-to-left !!!

Point and const Point are different types, so in the first iterpretation, you have a:

p5 = const Point(sumP1P2) . operator+ (Point(P3)) /*+ P4 awaiting interpretation */;
// whose search will be for a const LHS - i.e. "Point operator=(constPointRef) const;" - which is bound to fail.

The following will work:

const P& operator+(const P& rhs) const; // corresponds to const P& result = const P& lhs + const P& rhs
P operator+(P rhs) const; // corresponds to copy-by-value for all operands.
Fox
  • 2,078
  • 17
  • 18
0

The only problem is "const" Point operator+(const Point & rhs); remove that in the def and dec .. it will work

  • This doesn't answer the question, which was *why* he needs `const`. – David Schwartz Oct 27 '15 at 08:45
  • Your answer is right David Schwartz for the question he asked, but he is just started learning. So obviously I was giving why the problem occurred because of the constant on the return type .. That way he will learn what is const in return. – Sivakumar Arunachalam Oct 27 '15 at 10:46