overloading operator and & (not adress)

Hello! I've been working through the tutorial in the documentation section and I'm having some trouble wrapping my head around the overloading operator part.
the code:
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
28
29
30
31
32
// vectors: overloading operators example
#include <iostream>
using namespace std;

class CVector {
  public:
    int x,y;
    CVector () {};
    CVector (int,int);
    CVector operator + (CVector);
};

CVector::CVector (int a, int b) {
  x = a;
  y = b;
}

CVector CVector::operator+ (CVector param) {
  CVector temp;
  temp.x = x + param.x;
  temp.y = y + param.y;
  return (temp);
}

int main () {
  CVector a (3,1);
  CVector b (1,2);
  CVector c;
  c = a + b;
  cout << c.x << "," << c.y;
  return 0;
}


And my take on what happens:
CVector() {}; is a constructor function (called by c, param and temp when they are created)
CVector (int,int); is a constructor function (called by a and b when they are created)
CVector operator + (CVector); is an operator function of type CVector that returns a CVector, this function gets called at the + symbol in the line c = a + b;
c = a + b; can be read as c = a.operator+ (b);
so at a + b; the object a calls it's operator+ function and the object b is filled in as the parameter. in the function operator+ two new objects are made, param and temp.
a.x = 3 (defined in the main) param.x = 1 (takes the value from b.x) and temp.x = 0
the line temp.x = x + param.x; can be read like this: the integer x from the object temp is equal to the integer x from the object a added to the integer x from the object param.


is the above really what happens?


When I was searching for more information on overloading operators I found the following code:
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
28
29
30
31
32
33
#include <iostream>
using namespace std;

class complx
{
      double real,
             imag;
public:
      complx( double real = 0., double imag = 0.); // constructor
      complx operator+(const complx&) const;       // operator+()
};

// define constructor
complx::complx( double r, double i )
{
      real = r; imag = i;
}

// define overloaded + (plus) operator
complx complx::operator+ (const complx& c) const
{
      complx result;
      result.real = (this->real + c.real);
      result.imag = (this->imag + c.imag);
      return result;
}

int main()
{
      complx x(4,4);
      complx y(6,6);
      complx z = x + y; // calls complx::operator+()
}


I do not understand the way they created the operator+ function.
in this line:
complx operator+(const complx&) const;
it says complx& instead of just complx. Why do they do this? (it still works even when I remove the &)
They also say it is a const complx&, why exactly do they do this?
And the last part I dont get: they put another const at the end of the function before the semicolon. Why is this?

Any help would be very much appreciated!
complx& means that a reference to an object rather than a copy. Think of it like a pointer, just that you can call the function with an object rather than with an object pointer. The const part before the parameter is a guarantee to the user that if you write a = b + c, c will not be changed. The const part after the parameter list means b will also not be changed.

EDIT: If you wonder about why anyone would pass constant references: It's because this avoids copying the objects, which can be very inefficient especially with large objects.
Last edited on
Thanks for the reply, I think I understand better now. But I still have some questions. I have written down in words what I think happens in the execution of the second block of code in my first post:

x, y and z are objects of class complx. When x is created x.real=4 and x.imag=4 (same for y, but with a 6).
When z is created z.real and z.imag are undefined (they are 0?). but z.real will become x.real+y.real and the same goes for imag.
the + operator in the line complx z = x + y; makes sure that the object x calls its member operator function of the type complx. It fills in a reference of the object y for its parameter.
Object c will be created upon execution of the function, this is not a copy of the object y, but simply a reference to the object y.
this reference is a const, which means that y cannot be changed within the execution of that function.
The const after the parameter list makes sure that x cannot be changed throughout the execution of the object.
the first line of the operator+ function creates a new object of the class complx called result (this object will be destroyed at the end of the function)
result.real and result.imag are undefined (they are 0?).

The second line is something I do not understand very well, but I'll try to explain it.
result.real = (this->real + c.real); can be read as result.real = ((*this).real + c.real);
the member real of the object result will become equal to the member real of the object pointed by this (which is x.real in this case? it is x because x is the object that called the function?) added to the real of the object c which is a reference to the object y.
the same will happen for result.imag
the result will then be returned and z.real becomes result.real (same for imag) and the objects result and c are destroyed.



That was quite a lot of text, I hope that what I wrote is correct. I appreciate any help I can get.



So, the advantage of doing this over the code presented in the tutorial in the documentation on this site is that it makes sure that x and y cannot be changed. And it makes sure that a reference to the object y is created and not a copy (which costs less memory)
But, if you make sure that no statements in the function change either objects x or y, is it really necessary to make the object c and the operator function constants?
And if the object c was not a reference but a copy, would it really be a big problem? Won't the object be destroyed at the end of the function call anyway? I could see it becoming a problem if the object was huge and the function very complex so it would cost a lot of memory, but how often does that happen, really?


Last edited on
Well, to answer your question: Yes, this is pretty much almost correct. What you probably don't know is that after x+y, the default copy constructor of z will be called with the result of x+y as it's argument (this is done implicitly) which will, which you got right, copy the values of the result of x+y over to z.

As to your remaining questions.

To the consts: Yes, it is necessary. To explain this, imagine the + operator being declared this way instead of the normal one:
 
complx operator+(complx&); 


Now if you do this anywhere:
1
2
3
const complx x(5,5);
const complx y(6,6);
complx z = x+y;


It will not compile anymore (at least it shouldn't). Why? Because if you pass constant parameters to a function that takes nonconstant parameters (this only applies for pointers and references), you can't guarantee anymore that the value will not be changed. A variable being constant is pretty much a guarantee for the compiler that it's value won't be changed, which is why implicit casts from const to noncastant are usually forbidden by the compiler. What the consts pretty much do is, tell the compiler that it's ok to use these operators with constants.

And to the copy/reference thing: Yes, normally it wouldn't be a big problem. However, you never know what the user is going to with your classes, and if he should one shiny sunday decide he wants to add 5 billion complex numbers together, it would be better if he had the efficiency increase he gets from passing references instead of copies (also, while objects of this class might be small, this will not apply for all classes - think about a class that creates bitmap objects, which can easily get a few MBytes large...)
Topic archived. No new replies allowed.