Operator Overloading in C++

Discussion in 'C++' started by usmanmalik, Jan 3, 2014.

  1. usmanmalik

    usmanmalik New Member

    Joined:
    Dec 28, 2013
    Messages:
    19
    Likes Received:
    14
    Trophy Points:
    0
    Operator overloading is an extremely exciting feature of C++ language that allows you to simplify complex code into more readable and easy to understand code. For example what if we want to add two objects? Usually we will define some addition function that takes object to be added as a parameter and returns the result of addition of two objects.

    Suppose we have three objects p1,p2 and p3. Now if you want to add p2 and p3 objects and then store the result in p1 object, you will have to write complex code. The addition of objects can be achieved in many ways, following are three of them.

    p1 = AddObjects(p2,p3); or p1.AddObjects(p2,p3); or p1 = p2.AddObject(p3);

    All the above three methods are extremely complex and the resulting code is difficult to read. We want something simple and readable. What if we could add objects like:

    p1 = p2 + p3

    Operator overloading allows us to add two objects like we have added in the above line. Normally operators work with primitive data types like integer, strings etc. But with some effort we can achieve our desired functionality and can make these operators work with user defined data types as well.

    So, how can we define operator overloading?

    Answer: Operator overloading is the process of adding functionality to ordinary operators to make them work with objects.

    We know what function overloading is, what constructor overloading is, we can perform multiple task using the same function and constructor name. Similarly, we apply ordinary operators in a multiple ways to perform multiple tasks.

    Unary Operator Overloading



    Unary operators are those operators that act upon single operand. An operand is a variable upon which an operator acts to perform a particular function. Examples of unary operator are increment operator ++, decrement operator – and a simple minus operator.

    Overloading unary operator is an extremely simple and straight forward task. We will explain this with the help of an example. Consider Example1 for this purpose.

    Note: The code in Example1 has been written in Visual C++ and compiled with VS 2010.

    Example1
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    class  Item 
    {
    	int item_count;
    public:
    	Item(int a)
    	{
    		item_count = a;
    	}
    	void operator ++()
    	{
    		++item_count;
    	}
    
    	int getitemcount()
    	{
    		return item_count;
    	}
    };
    
    int main()
    {
    	Item item(10);
    	cout<<"The item count is:"<<item.getitemcount();
    	++ item;
    	cout<<"\nThe item count is:"<<item.getitemcount();
    }
    
    In example we have declared a class named item. The class has a constructor which takes integer type as argument and assigns the value passed to it to the member variable item_count. Class has a function named getitemcount() which returns the item_count variable. Note, above the getitemcount() function, we have function named void operator ++(). This is basically how we define the operator which we want to overload. Inside this operator function we have simply incremented the item_count variable by post fixing an increment operator to it.

    In the main function we simply created an object of the item class and passed an integer value of 10. Then we called the getitemcount() function of the object to display the item count.

    Next line is very important, here we incremented the object by writing ++item. Here item is not a primitive data type, it is a user defined object. Now what happens is when the compiler reach this line of code, it will call the increment operator function defined inside the item class and will execute whatever code is inside this function. In this case, the item_count integer variable will be incremented. In the following line we have simply displayed the value of the item_count variable by again calling the getitemcount() function. The output of this code will be as follows.

    Output1

    [​IMG]

    So, In order to overload an operator you will have to define a function inside the class upon which you want to apply the overloaded operator.
    It has three parts.
    1. First notice, we have the return type void, we can change it which we will see in future.
    2. The second part is the keyword operator.
    3. The third part is the operator you want to overload which is ++ in Example1.
    Now, what happens is whenever you prefix the increment operator before the object of class Item, the operator function we defined inside the class will be executed.

    Returning Values from the Operator

    Now, consider a scenario where we want to return some values from the operator. In Example1 the return type of the operator function was void. We want operator to return value. What can be done in this case? Suppose if we want to assign one incremented object into the other like

    Code:
    item2 = ++item1;
    If you write this line of code in Example1, it will not compile. You must be thinking then how to achieve this. Example2 explains this concept.

    Example2
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    class  Item 
    {
    	int item_count;	
    public:
    	Item(int a)
    	{
    		item_count = a;
    	}
    	Item()
    	{}
    	Item operator ++()
    	{
    		++item_count;
    		Item item1;
    		item1.item_count = item_count;
    		return item1;
    	}
    	int getitemcount()
    	{
    		return item_count;
    	}
    };
    int main()
    {
    	Item item1(10);
    	cout<<"The item1 count is:"<<item1.getitemcount();
    	Item item2;
    	item2= ++item1;
    	cout <<"\nitem1 is incremented and assigned to item2";
    	cout<<"\nThe item2 count is:"<<item2.getitemcount();
    }
    
    In Example2, we have changed the return type of operator function to Item. Inside the operator function we have declared an object of type Item. We have incremented the item_count of the class and assigned it to the item_count variable of the new created item1 object inside the operator function. Then we have returned this value to the calling function.

    In the main function we have declared two objects of class Item: item1 and item2. We have initialized item1 in the same way and have passed 10 to the constructor. We then displayed its value. After that comes the interesting part.

    We declared another object item2 of type Item and assigned the incremented value of item1. Now when ++ item1 is called it will again execute the code inside the operator function but this time it will return Item object which will be stored in item2. We have then displayed item2’s item_count value. The output of Example2 is as follows.

    Output2

    [​IMG]

    In Example2, in order to return item from the operator function, we have to write three lines. It can also be done using nameless temporary objects. In that case we have to write only one line. Example2 can be modified to explain this concept. Have a look at Example3.

    Example3
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    class  Item 
    {
    	int item_count;	
    public:
    	Item(int a)
    	{
    		item_count = a;
    	}
    	Item()
    	{}
    	Item operator ++()
    	{
    		++item_count;
    		return Item(item_count); // Nameless temporary object
    	}
    
    	int getitemcount()
    	{
    		return item_count;
    	}
    };
    
    int main()
    {
    	Item item1(10);
    
    	cout<<"The item1 count is:"<<item1.getitemcount();
    	Item item2;
    	item2= ++item1;
    	cout <<"\nitem1 is incremented and assigned to item2";
    	cout<<"\nThe item2 count is:"<<item2.getitemcount();
    }
    
    Here inside operator function in Item class we have used a nameless temporary object which will be destroyed when the function call ends but before that it will return us our desired object of Item.

    Binary Operator Overloading



    We have already explained how we can overload a unary operator. But usually we deal with binary operators most of the time. Binary operators are operators which act on two operands. For example, arithmetic operators can be considered binary operators such as '+’, '-', '*'. In this section we will explain how to overload binary operators. Suppose if we want to do something like, item3= item1 + item2. We can achieve it by overloading arithmetic ‘+’ operator.

    Friend Functions

    Before explaining binary operator overloading, another extremely important concept needs to be understood. Friend functions are the functions which are declared inside the body of the class and defined outside the body of the class.

    Binary operators should always be overloaded using friend function. There is a reason for that. If binary functions are overloaded using traditional operator functions as follows

    Code:
    Item Item :: operator+ (Item item1) { ... }
    It has certain limitations. It doesn’t implicitly convert both the operands. This means that using above function the results will be as follows.
    Code:
    Item item1, item2;
    Item2 = item1 +15; // this is permissible
    Item2 = 15 + item1 // this will not be compiled.
    
    Therefore in order to achieve anything like 15+ item1. You need implicit conversion of the operands which is possible only with the help of friend functions.

    Now, in order to further understand binary operator overloading, consider Example4. In this example we will explain how friend functions help in overloading binary operators. We will describe how all the four arithmetic operators can be overloaded.

    Example4
    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    class  Item 
    {
    public:
    	int item_count;	
    public:
    	Item(int a)
    	{
    		item_count = a;
    	}
    	Item()
    	{}
    	friend  Item operator+(Item i1, Item i2); // Friend function for Addition
    	friend  Item operator-(Item i1, Item i2); // Friend function for subtraction
    	friend  Item operator*(Item i1, Item i2);// Friend function for multiplication
    	friend  Item operator/(Item i1, Item i2);// Friend function for subtraction
    	int getitemcount()
    	{
    		return item_count;
    	}
    };
    
    Item operator + (Item i1, Item i2)
    {
    	return Item(i1.item_count + i2.item_count);
    }
    Item operator - (Item i1,  Item i2)
    {
    	return Item(i1.item_count - i2.item_count);
    }
    Item operator * (Item i1, Item i2)
    {
    	return Item(i1.item_count * i2.item_count);
    }
    Item operator / (Item i1, Item i2)
    {
    	return Item(i1.item_count / i2.item_count);
    }
    
    int main()
    {
    	Item Item1(50);
    	Item Item2(2);
    	Item OperatorResult = Item1 + Item2;
    	cout << "Addition operator overloading, adding items: " << OperatorResult.getitemcount()<<endl;
    
    	OperatorResult = Item1 - Item2;
    	cout << "Subtraction operator overloading, subtracting items: " << OperatorResult.getitemcount()<<endl;
    
    	OperatorResult = Item1 * Item2;
    	cout << "Multiplication operator overloading, multiplying items: " << OperatorResult.getitemcount()<<endl;
    
    	OperatorResult = Item1 / Item2;
    	cout << "Division operator overloading, dividing items: " << OperatorResult.getitemcount()<<endl;
    }
    
    Now, pay particular attention to the code in Example4. Inside the body of the class item, we have defined four friend functions for addition, subtraction, multiplication and subtraction. Notice, in order to declare a function as a friend function you just have to append the keyword append before the function.

    Friend functions are also often times used to communicate between two classes but here we will limit ourselves to operator overloading. You can see that outside the body of the class, we have provided complete definition of all the four friend functions that we declared inside the class.

    These functions take two objects as a parameter. Inside the body they add, subtract, multiply or divide the item_count variables of both the passed objects and return the result via nameless temporary object.

    Inside the main function, we have created two objects of class Item and initialized them by passing integer values to their respective constructors. We have created a third object of the same Item class and have one by one stored the result of the addition, subtraction, multiplication and division into OperatorResult object of item class. We have then printed the resultant values of the objects on screen.

    The output of Example4 is as follows. We have initialized two Item objects with 50 and 2 and here are the results of all the arithmetic operators.

    Output4

    [​IMG]

    In Example4 we have overloaded operators to add, multiply, subtract and divide two operands. However, the method described in Example4 can also be used to add, subtract, and multiply more than two operands. For example, you can also do something like

    Code:
    Itemresult = item1 + item2 + item3.
    The result will be sum of these three objects.

    Therefore, in Example4 we have explained how can we overload four basic arithmetic operators with the help of friend functions and achieve the desired result. This method can be can be extended to overload assignment and comparison operators as well.

    In short, operator overloading is an extremely handy feature of object oriented programming and if used well can simplify complex pieces of code into simpler and easier to read. It is always more interesting to deal with objects as primitive data type and with the help of operators you can somehow achieve this functionality.
     
    shabbir likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice