Overloading the + operator?

Hello everyone.
I was reading about + operator overloading and I have a question. I understand the concept and everything is clear in this one:

1
2
3
4
5
  Cents operator+(const Cents &c1, const Cents &c2)
{
    // use the Cents constructor and operator+(int, int)
    return Cents(c1.m_nCents + c2.m_nCents);
}


but the problem occurs here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// overloading operators example
#include <iostream>
using namespace std;

class CVector {
  public:
    int x,y;
    CVector () {};
    CVector (int a,int b) : x(a), y(b) {}
    CVector operator + (const CVector&);
};
//************************************UNDER THIS
CVector CVector::operator+ (const CVector& param) {
  CVector temp;
  temp.x = x + param.x;
  temp.y = y + param.y;
  return temp;
}

int main () {
  CVector foo (3,1);
  CVector bar (1,2);
  CVector result;
  result = foo + bar;
  cout << result.x << ',' << result.y << '\n';
  return 0;
}

Overator overloading function in this example has only one parameter. And now I am confused about this. How does it add up objects boo and foo when it has only one parameter?
In the line: temp.x = x + param.x;,what does the solo "x" represent (I mean the solo x,not the param.x)?
This:

1
2
3
4
5
6
CVector CVector::operator+ (const CVector& param) {
  CVector temp;
  temp.x = x + param.x;
  temp.y = y + param.y;
  return temp;
}


is the same as this:
1
2
3
4
5
6
CVector CVector::operator+ (const CVector& param) {
  CVector temp;
  temp.x = this->x + param.x; //  this->x
  temp.y = this->y + param.y; //  this->y
  return temp;
}


is the same as this:
1
2
3
4
5
6
CVector operator+ (const CVector& a, const CVector& param) {
  CVector temp;
  temp.x = a.x + param.x;
  temp.y = a.y + param.y;
  return temp;
}



When you have the operator as part of the class... the this object automatically becomes the left-hand argument. So only 1 object needs to be passed as the right hand object.

When the operator is not part of the class, there is no this object, so you have to pass 2 arguments.


The this object is the object on which the member function (or operator in this case) is being acted on. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class CVector
{
  public:
    int getX() { return x; } // <- returns this->x
};

//...

int main()
{
    CVector foo(3,1);

    int x = foo.getX();  // <- here, 'foo' becomes the 'this' object
      // so this get's foo's x value
    cout << x;  // <- so this will print 3
}


With operators it's the same:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CVector {
    //...
    CVector operator + (const CVector& param);
};

//...

int main()
{
  CVector foo (3,1);
  CVector bar (1,2);
  CVector result;
  result = foo + bar; // <- here, foo becomes the 'this' object, and bar becomes the 'param'
     // object.
}
If you look closely, in the first example, the operator is defined as a free function, and therefore needs to be supplied with two objects to add.

In the second example, the operator is a member of the CVector class. The two operands will be this and param. At lines 15 and 16, it's adding the x and y values from param to the x and y values belonging to its own instance, i.e. this.

EDIT: Ninja'd by Disch. Not for the first time :(
Last edited on
Thank you both for fast answers. I appreaciate it. It is clear as sky now.
:)
I have one more question. Here: CVector operator + (const CVector&);, why does the author use const value, and &, when everything works with no const and no & ?
1
2
3
void byval(CVector param);
void byref(CVector& param);
void bycref(const CVector& param);


Here we have 3 functions which pass the parameter in different ways.

The first function passes the parameter "by value". This means that 'param' will actually be a copy of the object. So if you were to call the function like so:

1
2
CVector a;
byval( a );


... 'a' and 'param' would be two separate objects. The 'byval' function could make changes to the 'param' object, and it would not change the 'a' object because they are separate things.



On the other hand... the 'byref' function passes the object by reference. Which means 'a' and 'param' will both refer to the same object. Changes made to 'param' inside the byref function will change the 'a' object because they are one and the same.


The const reference version ('bycref') is the same as the 'byref' version in that both 'a' and 'param' refer to the same object. The difference is that the const keyword prevents you from making changes to 'param' because it's treated as a constant.



With complex objects (classes) it's typically preferred to pass them by const reference because it avoids having to copy the object. Creating a copy can be computationally expensive... so passing by value is often avoided.

However with basic/small types (like builtin types such as int/double/etc), the copy is trivial and it can possibly be faster to pass them by value. So it really all depends.
The difference is that the const keyword prevents you from making changes to 'param' because it's treated as a constant.

And, furthermore, indicates clearly to anyone else using your class that the operator is guaranteed not to change the state of param. (*)

Creating a copy can be computationally expensive

And can have unwanted side-effects, depending on what's in the copy constructor, and what's in the copy constructors of the data members.

(*) Assuming you haven't done anything silly with mutable data members... but that's an advanced topic.
Topic archived. No new replies allowed.