L14 - Operator overloading

#ece244

overloading the == operator: operator==

another common operator we can overload is the == operator. We can use this to compare equality, but technically we can do whatever we want in the operator== function. But let's just say that we want to compare for two objects for equality. We must then:

continued example from L13: operator+ and operator==

#include <iostream>
using namespace std;

class Complex {
	private:
		double real, img;
	public:
		Complex() { // first constructor
			real = 0.0;
			img = 0.0;
		}
		Complex (double r, double i) { // second constructor
			real = r;
			img = i;
		}
		Complex operator+(const Complex &rhs) const {
			// as good practice, we should use a reference
			// instead of a pass by value to save on memory
			// const Complex &rhs prevents changes to rhs
			// const {} prevents changes to object you invoke function on
			// we do this because we don't want to change x and y; we just want to
			// create a new object that is the sum
			Complex temp;
			temp.real = real + rhs.real;
			temp.img = img + rhs.img;
			return temp; // returning a COPY of temp (by value)
			// we can't return a reference here because the object will no longer exist
			// in the memory once this function goes out of scope
		}
	bool operator==(const Complex& rhs) {
		// we don't have to pass the lhs because we are invoking the function
		// on the lhs object
		if (real == rhs.real && img == rhs.img) {
			return true;
		} else {
			return false;
		}
		// or we could just return (reall==rhs.real)&&(img==rhs.img);
	}
}

int main(void) {
	Complex x(3,4); // calls second constructor
	Complex y(5,6); // calls second constructor
	Complex z; // calls first constructor
	
	z = (x + y);
	if (x == y) {
		// we can only do this because we defined our own operator== above
		
	}
}
Creating a function operator+ replaces the + operator in the main function

i.e., (x+y) calls .operator+() automatically. However, this depends on the data types passed through. If the data types differ from what we define, we need to define a new function in the class.


default operator=

By default, the compiler will give a default operator= function to all classes if not implemented. This sets all data members of LHS to RHS.

e.g. z=q; is the same as z.operator=(q);, which sets all data members on LHS to RHS.

What does this look like?

#include <iostream>
using namespace std;

class Complex {
	private:
		double real, img;
	public:
		Complex() { // first constructor
			real = 0.0;
			img = 0.0;
		}
		Complex (double r, double i) { // second constructor
			real = r;
			img = i;
		}
		Complex& operator=(const Complex& rhs);
		// we return by reference here to obey the C++ standard
		// this returns the original object on which we invoked the function
		// but we do NOT add a const because that would prevent us from making
		// any changes to the object
}

Complex::operator=(const Complex& rhs) {
	real = rhs.real;
	img = rhs.img;
	return *this; // returns the object that the function is called on
}

int main(void) {
	Complex x(3,4); // calls second constructor
	Complex y(5,6); // calls second constructor
	Complex z; // calls first constructor
	
	z = (y = x);
	// same as calling z.operator(y.operator=(x));
}
Notes:

So, the function header looks like this:

Complex& operator=(const Complex& rhs)

In C++, we need to return the object on the RHS from operator= in a chained assignment operator.


chained assignments

In C/C++, doing z = y = x:

  1. first calls y = x, i..e y.operator=(x)
  2. then, calls z = y, i.e. z.operator(y)
    In essence, C/C++ read from right to left with chained assignments.
    file-20251101000744528.png|500

this as a return value in a class function

this is a pointer to the object on which the class function is invoked on.

e.g. in z = operator=(y), this points to z in the operator= function