CS210 Lab: Operator Overloading and "This"


Prelab Questions:

For a review of relevant topics click here.

Highlights of This Lab:

Lab Exercise:


Click the little computer above for a detailed description.

1. Definition of Operator Overloading

Operator Overloading allows you to redefine the functioning of certain operators, such as "+", "-", "=", ">>", "<<" (a complete chart is below).

The question is: why would you want to do this?
Because, sometimes it is more intuitive to simply be able to write the short form of an operation. For instance consider this example of adding two arrays.

#include <iostream>
using namespace std;

#define MAXARRAY 5

int main ()
{

	int array1[MAXARRAY], array2[MAXARRAY], array3[MAXARRAY];
	int i=0;
	
	//INITIALIZE 
	for (i=0; i<MAXARRAY; i++)
	{
		array1[i]=i;
		array2[i]=i+3;
	}
	
	//ADD 
	for (i=0; i<MAXARRAY; i++)
		array3[i]=array1[i] + array2[i];
	
	//PRINT 
	cout << "array1   array2   array3" << endl;
	for (i=0; i<MAXARRAY; i++)
		cout << array1[i] << "        " 
		     << array2[i] << "        " 
		     << array3[i] << endl;

	return 0;
}
Instead of writing a for statement every time you add two arrays together, it would be nice to instead write:
array3=array1 + array2;
To be able to do this, you must overload the "+" operator. To overload any operator, you use the keyword operator and then the operator character. We will discuss the details in Section 2.

The following table (taken from C++ Primer, Lippman and Lajoie) is the predefined set of C++ operators that may be overloaded:

Table of Overloadable Operators
+ - * / % ^ & | ~
! , = < > <= >= ++ --
<< >> == != && || += -= /=
%= ^= &= |= *= <<= >>= [] ()
-> ->* new new[] delete delete[]      

NOTE: the point of operator overloading is to be intuitive. You do not want to assign a confusing operator name. For instance, you do not want to overload the "+" when the function actually performs subtraction.


2. Operator Overloading Using a Friend

Given the code above, we want to overload the addition operator to write:
array3=array1 + array2;
This involves some manipulation on the code in Section 1.

Let's show the code for the myarray class and the overloaded "+":

class myarray
{
private:
	int value[MAXARRAY];

public:
	void setvalue(int index, int newvalue){
		value[index]=newvalue;}
	int getvalue(int index){
		return value[index];}
	friend myarray operator+(myarray array1, myarray array2); 
};
myarray operator+(myarray array1, myarray array2)
{
	myarray temparray;
	for (int i=0; i<MAXARRAY; i++)
		temparray.value[i]=array1.value[i] + array2.value[i];
	return temparray;
}
int main ()
{

	myarray array1, array2, array3;
	
	//INITIALIZE 
	for (int i=0; i<MAXARRAY; i++)
	{
		array1.setvalue(i,i);
		array2.setvalue(i,i+3);
	}
	
	//ADD 
	array3=array1 + array2; 
	
	//PRINT 
	cout << "array1   array2   array3" << endl;
	for (i=0; i<MAXARRAY; i++)
		cout << array1.getvalue(i) << "        " 
		     << array2.getvalue(i) << "        " 
		     << array3.getvalue(i) << endl;

	return 0;
}
Notice the following:

 

2.1 A Noteworthy "friend"

Pay attention to the body of the operator+ function. We are trying to access the value array, which is a private data member. Normally, this would yield a compiler error. We have two options:
  1. make value a public data member so that anything can access it. This is NOT a good option because it goes against the principles of object oriented programming. Anything could then modify the value array.
  2. make the operator+ function a friend to myarray. This is a better option. When we specify that the operator+ function is a "friend", we trust it enough to give it access to the private data members in myarrray. Therefore, in the body of the operator+ function we can access the value array.

3. Member Operator Overloading

Another way that we can overload an operator is as a member function.

The code would look like the following:

#include <iostream>
using namespace std;

#define MAXARRAY 5
class myarray 
{
private:
	int value[MAXARRAY];

public:
	void setvalue(int index, int newvalue){
		value[index]=newvalue;}
	int getvalue(int index){
		return value[index];}
	myarray operator+(myarray array2)
	{
		myarray temparray;
		for (int i=0; i<MAXARRAY; i++)
			temparray.value[i]=value[i] + array2.value[i];
		return temparray;
	}
};

int main ()
{
   . . .
}
Note: How can that be?

You can view the following code:

array3=array1 + array2;
as being rewritten by the compiler as:
array3=array1.operator+(array2);
This is because array1 is an object of myarray class, and operator+ is a member function. It is the same idea as calling another member function such as: array1.getvalue(0);.

In the overloaded operator case however, the compiler is smart enough to figure out that when you write array1 + array2, what you actually mean is array1.operator+(array2).

This is where this pointer comes in handy.


4. The "this" Pointer

For an introduction to the "this" Pointer, click here

Whenever a member function is called, an implicit argument, specifically, a pointer to the object that generated the call, is automatically passed to the function. This pointer is called this.


How do you know when to use what?

To summarize, sometimes you have a choice of defining the overloaded operator function as a member function or a non-member function. It is a matter of preference as to which you find more comfortable and easy. However, there are two situations where you are forced to use only one of the two options:
  1. When the left-hand side is not an object (for instance, when the left-hand side is a integer) such as: you must define it as a non-member function

  2. For the following operators, you can only define them as member functions You will get a compiler error if you try and overload these operators as non-member functions.
What is the difference between member and non-member functions?

5. Lab Exercise

There are two parts to the exercise. The first part is a pen and paper component where you make a table to show your understanding of overloading operators in the two ways discussed above—as member functions and as non-member functions. The second part is programming.

Part 1

Study the following tables: write out the answer on a piece of paper.

Assume that a and b are myarray objects. Specify the corresponding member and non-member prototypes for the following overloaded operator expressions. If you cannot define the prototypes in one of these ways, please specify with an N/A. The first two have been completed for you.

Expression  Defined as Member Functions  Defined as Non-Member Functions
 a+b  myarray operator+(myarray b)   myarray operator+(myarray a, myarray b) 
 1+a  N/A  myarray operator+(int a, myarray b)
 a+1    
 a=b    
 a>b    
 10<b    
 cin>>a    

Specify which of the following are Member Functions and which are Non-Member Functions:

  Member Non-Member
max(a,b)    
a.printit()    
int myclass::sum(void)    
float min(float a, float b)    

Part 2

For part 2, if you are using Replit, fork the project using the link on URcourses. If you are using Visual Studio, download the file and follow the instructions from the Lab 1 notes on creating a C++ project in Visual Studio.

  • Copy this file to your computer.
    The file: 	arrayadder.cpp
    
    

    Your primary tasks for this exercise are:

    1. Modify the code so that you overload the "-" operator to subtract array2 from array1:
      • First overload it as a member function in the myarray class.
      • Second overload it as a non-member function
    2. Overload the "<<" (insertion operator) so that it will print the entire array on one line

    Steps include:

  • Build and run the executable file (this is just to ensure that the program is working). You should get the following output:
    array1   array2   array3
    0        3        3
    1        4        5
    2        5        7
    3        6        9
    4        7        11
    

  • Add some code in the myarray class to overload the "-" operator

  • Add some code in main (after the following line)
    	array3=array1 + array2; 
    
    to subtract array2 from array1 (and store the result in array3).

  • Build and run the executable file. You should get the following output:
    array1   array2   array3
    0        3        -3
    1        4        -3
    2        5        -3
    3        6        -3
    4        7        -3
    

  • Overload the "-" operator as an non-member function. (Making appropriate changes--as in this section)

  • Build and run the executable file. You should get the same output as the previous run.

  • Now, overload the "<<" (insertion operator) so that it will print one array per line.
    Hints: The prototype will look like this:
    ostream& operator<<(ostream& os, myarray array)
    
    You make use of os in lines like the following:
    os << "newarray:  ";
    
    (this puts "newarray: " into the output stream, os)
    Don't forget to:
    	return os;
    

  • Change the calls to cout in main so that you only have a single line:
    cout << array1 << array2 << array3;
    

  • Build and run the executable file. You should get output similar to the following:
    newarray:  0      1     2     3    4
    newarray:  3      4     5     6    7
    newarray:  -3    -3    -3    -3    -3
    

    6. Postlab Exercises

    For postlab exercices, click here.

    CS Department Home Page
    CS210 labs
    University of Regina

    Copyright: Department of Computer Science, University of Regina.