Operator and function overloading

Before we dive into the tutorial and learn about overloading, let’s first discuss overloading types. Overloading is of two types:

  • Operator Overloading: Operator overloading is used to redefine how standard operators are used within user-defined objects.
  • Function Overloading: Function overloading is a feature of polymorphism where a function can have the same name but different parameters; however, they can have the same return type.

Operator Overloading

Let’s first understand an essential element of a class, the copy constructor. Copy constructors are created when we initialize an object of a class with another object of the same class, as shown below.

// creating an object round of the type circle and passing the value of radius
Circle round(3);
// copy constructor called
Circle c = round;

Copy constructors is a few other times as well:

  • A function is called with the parameter of the class object
  • A function returns the value that is an object of the class

However, if two objects are initialized and then an object is copied into another using the assignment, we need to overload the assignment operator.

Assignment Operator

Consider an example where we want an object to have the value of the other object that is of the same class. What do we do? we overload the assignment operator as demonstrated below:

Circle c(5); // initialize a circle with radius 5
Circle c1(3); // initialize a circle with radius 3
// using assignment operator
c = c1

In the above code, C++ performs memberwise copy and copies c1 to c leaving pointers in both objects pointing to the same memory location. Here copy constructors cannot be used even though they perform the same function because copy constructors are used when an object is being initialized at creation time.

To address the problems that arise from memberwise assignments of objects, we need to overload the assignment operator. Now the overloaded assignment operator does something different than memberwise copy. We can overload the assignment operator as a member of a class.

The syntax is as shown below:

// return type: DynamicSafeArray, function name: operator= , parameter: object of right hand side
DynamicSafeArray &operator=(const DynamicSafeArray &rhs)
#include<iostream>
#include <stdexcept>
#include<string.h>
#include<cstdlib>
using namespace std;
//Exception class
class Arrayindexoutofbound:public std::runtime_error
{
	public:
		//default constructor of exception class with error message
    	Arrayindexoutofbound():std::runtime_error("Array index out of bound!")
    	{
		}
};
//Safe array class
class DynamicSafeArray
{
	private:
		int *data;
		int size;
	public:
		//default constructor
		DynamicSafeArray()
		{
			data=new int [100];
			size=100;
			memset(data,0,sizeof(int)*100);
		}
		//parameterized constructor
		DynamicSafeArray(int s)
		{
			this->size=s;
			this->data=new int[s];
			memset(this->data,0,sizeof(int)*s);
		}
		int getsize() const
		{
			return size;
		}
		int getdata() const
		{
			return *data;
		}
		//copy constructor
		DynamicSafeArray(const DynamicSafeArray &rhs)
		{
			size=rhs.size;
			data=new int [size];
			memcpy(rhs.data,data,sizeof(int)*size);
		}
		//assignment operator overloaded
		DynamicSafeArray &operator=(const DynamicSafeArray &rhs)
		{
			if(this!=&rhs)
			{
				if(data!=0)
				{
					delete this->data;
					data=0;
					size;
					size=rhs.size;
					data=new int[size];
					memcpy(rhs.data,this->data,sizeof(int)*this->size);
				}
				return *this;
			}
		}
}

The above class looks kind of complex but is pretty simple. We have created our own array class that consists of a default constructor, copy constructor, assignment operator, and getter/setters. To call the assignment operator, we simple write the code below in the main function:

int main()
{
	// Initialized 2 objects of Dynamic Safe Array
	DynamicSafeArray array(7);
	DynamicSafeArray array1(10);
        // calling assignment operator
	array = array1
}

The special thing about our assignment operator is that it behaves like a natural, built-in assignment operator. To explain this, let’s see an example. In the compiler, we can do a = b = c, and our assignment operator does just that!

So in reality the address of the object is accessed through *this pointer.

We can overload many operators like athematic operators, prefix, postfix, stream operators, and the list goes on. Since we have talked about the dynamic, safe array class, let’s discuss the subscript([]) operator that performs bound checking that C++ lacks.

Overloading the [] operator

The code below will be added to the DynamicSafeArray class.

int &operator[](int i)
{
  if(i<0 || i>size)
  throw(Arrayindexoutofbound());   //exception called
  else
  return *(data+i);
}

This code throws an exception if the array index goes out of bounds. The bound condition for the index is that it should not be less than zero, and it should not be greater than the array size. If we were to use the subscript operator normally and the index got out of bound somehow, no exception would be displayed; instead, the program would crash.

Overloading Arithmetic Operators

Let’s suppose a class wants to add or subtract 2 measurements and then compare them. We can observe this example with the code below.

 #include <iostream>
 using namespace std;

 class Length
 {
 private:
 int len_inches;
 public:
    //parametrized constructor
 Length(int feet, int inches)
 {
 setLength(feet, inches);
 }
   //parametrized constructor
 Length(int inches){ len_inches = inches; }
   //getter/setters
 int getFeet(){ return len_inches / 12; }
 int getInches() { return len_inches % 12; }
 void setLength(int feet, int inches)
 {
 len_inches = 12 *feet + inches;
 }
   //friend functions
 friend Length operator+(Length a, Length b);
 friend Length operator-(Length a, Length b);
 friend bool operator< (Length a, Length b);
 friend bool operator== (Length a, Length b);
 };


 // Overloaded operator + *
 Length operator+(Length a, Length b)
 {
 return Length(a.len_inches + b.len_inches);
 }

// Overloaded operator - *
 Length operator-(Length a, Length b)
 {
 return Length(a.len_inches - b.len_inches);
 }

 // Overloaded operator == *
 bool operator==(Length a, Length b)
 {
 return a.len_inches == b.len_inches;
 }

 // Overloaded operator < *
 bool operator<(Length a, Length b)
 {
 return a.len_inches < b.len_inches;
 }

int main()
 {
 Length first(0), second(0), third(0);
 int f, i;
 cout << "Enter a distance in feet and inches: ";
 cin >> f;
 cin >> i;
 first.setLength(f, i);
 cout << "Enter another distance in feet and inches: ";
 cin >> f ;
 cin >> i;
 second.setLength(f, i);

 // Testing + operator
 third = first + second;
 cout << "first + second = ";
 cout << third.getFeet() << " feet, ";
 cout << third.getInches() << " inches."<<endl;
  // testing - operator
 third = first - second;
 cout << "first - second = ";
 cout << third.getFeet() << " feet, ";
 cout << third.getInches() << " inches."<< endl;

 // Testing == operator
 cout << "first == second = ";
 if (first == second) 
 cout << "true"; 
 else 
 cout << "false";
 cout << endl;
  // Testing < operator
 cout << "first < second = ";
 if (first < second) 
 cout << "true"; 
 else 
 cout << "false";
 cout <<endl;

}

In the above code, we will enter a length in inches and feet, and then we have overloaded the operators that will add/subtract the value in inches and give the result. We have also overloaded less than and equal to operators to compare the two objects of the class length.

Overloading Stream Operators

Overloading the stream operators comes in very handy as it allows the objects to be converted into text and then output to cout or any file. The code below shows how to stream insertion and extraction operators are overloaded.


 // Overloaded stream extraction operator >> *
 istream &operator>>(istream &in, Length &a)
 {
 // Prompt for and read the object data
 int feet, inches;
 cout << "Enter feet: ";
 in >> feet;
 cout << "Enter inches: ";
 in >> inches;


 // Modify the object a with the data and return
 a.setLength(feet, inches);
 return in;
 }

 // Overloaded stream insertion operator << *
 ostream &operator<<(ostream& out, Length a)
 {
 out << a.getFeet() << " feet, " << a.getInches() << " inches";
 return out;
 }

int main() 
{
 Length first(0)
 cout << "\nDemonstrating input and output operators.\n";
 cin >> first;
 cout << "You entered " << first << "." << endl;

}

As we can see the use of stream operators simplify our work of taking input and producing an output. cin >> first takes the feet and inches and then cout displays that result. This is hassle free ad we don’t need to worry about taking 2 inputs for feat and inches separately and then discovering how to print them. We can just overload the operators and our life will become easier.

Things to Keep in Mind while Overloading Operators

  • The new operator cannot be overloaded.
  • The overloaded operator must contain one user-defined operand as a function argument.
  • Unary operators are overloaded as member functions; they do not take arguments; however, if they are overloaded as a friend function, they take one argument.

Function Overloading

Function overloading can be very useful when we cannot find different meaningful names for the same function in a class. This scenario occurs quite a lot; even the built-in libraries rely heavily on function overloading.

An example of function overloading is shown below:

1.void add(int a, int b);
2.void add(float a, float b);

If we pass integer values to the add function, we will be using function number 1, and if we pass float values, we will be using function number 2.

Function Overriding

Just like overloading, function overriding is also an intriguing feature of object-oriented languages. Overriding is a feature of classes that inherit other classes. The derived class can implement the functions in the base class with the same name and even the same argument list.

Conclusion

In this article, we have discovered some amazing ideas on how to make our code easier. We have discussed some concepts of function over and overriding as well; however, we intend to dig deeper into these concepts, so stay tuned!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *