Operator Overloading- III


The following topics are covered in this section:


Adding Objects with Built-in (fundamental) data types

So far we’ve seen binary operators operating on two objects. Now we’ll see how to overload a binary operator such that it will add an object along with an integer (which is a fundamental data type).

class timer
{ private :
        int countdown;
public :
timer ( ) : countdown (100)
{ }
timer (int t) : countdown (t)
{ }
int display ( )
{
return countdown;
}
timer& operator+ (int j)
{
countdown=countdown+j;
return *this;
}
};
int main ( )
{timer c1, c2(98),c3(94);
cout<<"\nInitial c1 value : "<<c1.display( );
cout<<"\nInitial c2 value : "<<c2.display( );
cout<<"\nInitial c3 value : "<<c3.display( );
c1+100;
cout<<"\n\nFinal c1 value : "<<c1.display( );
cout<<"\nFinal c2 value : "<<c2.display( );
cout<<"\nFinal c3 value : "<<c3.display( );
return 0;
}

The output is:

Initial c1 value : 100
Initial c2 value : 98
Initial c3 value : 94
Final c1 value : 200
Final c2 value : 98
Final c3 value : 94

When the compiler encounters:

c1+100;

it knows that the object c1 is invoking the operator+ member function. This function has an integer as its argument and 100 is passed by value to the integer ‘j’. The rest of the program is as normal.

Another point to note is about the drawback of using the overloaded operator function as a member function. In the above program if you tried:

100 + c1;

it wouldn’t work! Why? Because according to what we’ve learnt in operator overloading, the object on the left of the operator will invoke the overloaded member function. But now the operand on the left of the operator is an integer and the compiler does not know what to do.

The problem is because the operator+ function is a member function of the class and it is passed the ‘this’ pointer. The problem can be avoided if you made use of friend functions. In friend functions the ‘this’ pointer is not passed (and they are not members of the class). So you can specify the order of the arguments when you overload an operator using a friend function.

The program below illustrates the use of friend function to solve this problem:

#include <iostream.h>
class timer
{ private :
    int countdown;
public :
timer ( ) : countdown (100)
{ }
timer (int t) : countdown (t)
{ }
int display ( )
{
return countdown;
}
friend timer& operator+ (int, timer&);
friend timer& operator+ (timer&, int);
};
timer& operator+ (int j, timer &x)
{x.countdown=x.countdown+j;
timer *p=&x;
return *p;
}
timer& operator+ (timer &y, int k)
{y.countdown=y.countdown+k;
timer *pt=&y;
return *pt;
}
int main ( )
{timer c1, c2(98),c3(94);
cout<<"\nInitial c1 value : "<<c1.display( );
cout<<"\nInitial c2 value : "<<c2.display( );
cout<<"\nInitial c3 value : "<<c3.display( );
100+c1;
c1+100;
cout<<"\n\nFinal c1 value : "<<c1.display( );
cout<<"\nFinal c2 value : "<<c2.display( );
cout<<"\nFinal c3 value : "<<c3.display( );
return 0;
}

The result is:

Initial c1 value : 100
Initial c2 value : 98
Initial c3 value : 94
Final c1 value : 300
Final c2 value : 98
Final c3 value : 94

As you can see, we have made use of two friend functions to overload the + operator so that it can operate with an integer value on either side of the operator. The friend function definition might appear really strange. Why should we write:

timer& operator+ (int j, timer &x)
{
x.countdown = x.countdown+j;
timer *p = &x;
return *p;
}

Why should we attempt to return a reference rather than doing the straightforward method of returning an object as below:

timer operator+ (int j, timer &x)
{
x.countdown = x.countdown+j;
return x;
}

Well, this is quite correct but you have to bear in mind that the copy constructor is invoked each time you return an object from a function (which means that the destructor will be copied exactly to a temporary object bit by bit).

Try it: You can check this idea by creating your destructor function for the class. Whenever you return an object from a function, you will see that the destructor function is invoked whereas if you return a reference to an object, the destructor function will not be invoked.

In the above program this won’t cause any problems because we are not making use of the ‘new’ and ‘delete’ operators. But in case you make use of them then you should take note of this point. The same is the reason for using pass by reference in the above program.


Overloading ‘new’ and ‘delete’ operators

The ‘new’ and ‘delete’ operators are usually sufficient for most programs but there might be cases wherein you want to overload them as well. Some important points are:

The syntax for overloading ‘new’ and ‘delete’ are:

void* operator new (size_t n)
{
    //allocate memory and return the address (a void pointer)
}

void operator delete (void *p)
{
    //free the memory space pointer to by the pointer ‘p’
}

You will notice that the parameter for ‘new’ is:

size_t n;

size_t is a numerical data type defined by the system to specify memory size in bytes. For instance if you use ‘new’ to create a character, the value of n (i.e. the argument passed to ‘n’) will be 1. If you pass a ‘double’ quantity then the value of ‘n’ will be 8 (you needn’t worry about this).

The program below overloads the ‘new’ and ‘delete’ operators globally.

#include <iostream.h>
#include <stdlib.h>
void* operator new(size_t n)
{

cout<<endl<<"overloaded new";
void *ptr;
ptr = malloc(n);
return ptr;
}
void operator delete(void *p)
{cout<<endl<<"overloaded delete";
free(p);
}
int main( )
{int *p = new int;
*p=20;
cout<<"\n The value is : "<<*p; //value of 20
delete p;
cout<<"\n The value after deleting is : "<<*p; //some invalid value
return 0;
}

The output will be:

overloaded new
The value is : 20
overloaded delete
The value after deleting is : 4325404

We make use of C functions malloc( ) and free ( ) to overload the ‘new’ and ‘delete’ operators in the above program.

void* operator new [ ] (size_t n)
{
//allocate memory and return the address (a void pointer)
}
void operator delete [ ] (void *p)
{
//free the memory space pointer to by the pointer ‘p’
}

Recap


Go back to the Contents Page 2


Copyright © 2004 Sethu Subramanian All rights reserved.