<Previous Lesson

Introduction to Programming

Next Lesson>

Lesson#32

Lesson 32

Summary


18) Recap
19) Overloading Minus Operator
20) Operators with Date Class
21) Unary Operators


Recap


Before further discussing the concept of the ‘Overloading’, we will recapture the things
dilated upon in the previous lecture. It is necessary to know that new operators i.e. new
symbols cannot be introduced. Only existing symbols can be overloaded. Overloading of
operators is exactly like writing functions. However, one should remain close to the
original meaning of the operator. Similarly, it is good not to define something in opposite
terms e.g. ‘plus operator is doing subtraction or multiplication operator carrying out
division’. We can do that but it will ultimately a bad thing for a programmer. It makes
our program practically unreadable and mis-interpretable. Under operator overloading
technique, the binary and unary operators will remain unchanged that is we cannot make
unary operator work as binary operator or vice versa. In the previous lectures, we also
came across some concepts in terms of driving force behind the operator, e.g. in case of
binary operator, the driving force is left hand operand. We have also studied when to use
member operators and non-member operators. Today we continue discussion on ‘use of
operators’.

Overloading Minus Operator


Let’s define minus operator ( - ) with special reference to the complex class. The process
of defining the minus operator is quite similar to that of the plus operator. Let’s first
understand the action of minus operator. It is a binary operator, having two arguments. In
this case, both the arguments will be complex numbers. When we subtract two complex
Page 404
numbers, it always return a complex number. Here the subtraction of complex numbers is
defined as, ‘subtract the real part from real part and subtract the imaginary part from the
imaginary one”. So a member operator will look like as under:
Complex operator – (Complex c)
As we are defining it as a member operator, only one argument will be passed to it. It is
going to be on the right hand side of the minus operator. The left-hand-side will call this
as it is already available to this function. In the body, we will declare a temporary
Complex number. This means that the real part of this temporary complex number is the
difference of the calling Complex number and the Complex number passed as argument
i.e.:
tmp.real = real – c.real;
In the next line, we calculate the difference of imaginary part as:
tmp.imag = imag – c.image;
and return the tmp Complex number. By defining, the minus operator does not mean that
minus equal operator has also been defined. If we want to overload the minus equal
operator (-=), it is necessary to define it. Let’s see how the defining process is carried out.
Minus equal to operator like the plus equal to operator behaves in the way that the value
of calling party (i.e. the complex number which is on the left hand side) will also be
changed. So now we will see that the number itself changing the value when it takes part
in the minus equal to operator. Again, we will make this a member function. So only one
argument will be passed to it. The complex number will be on the right hand side of the
minus equal to operator. In the body of the function, there is no need of any temporary
complex number as we are going to change the number on the left hand side of the minus
equal to operator. We can write it as:
real -= c.real;
imag -= c.image;
Here c is the complex number which is passed as an argument. Now the minus equal to (-
=) operator, used in the above statements, is an ordinary minus equal to operator for the
integers defined by the C++. So this is a classic example of overloading i.e. the operator
being overloaded is using the original or basic operator of same type. That is the end of
this function. The original number has been changed. We can return its reference. It
depends on its usage.
Here is the code:
// The minus operator definition
Complex Complex::operator - ( Complex c )
{
Complex tmp; // defining a temporary var
Page 405
tmp.real = real - c.real;
tmp.imag = imag - c.imag;
return tmp;
}
// The -= operator definition
Complex Complex::operator -= ( Complex c )
{
real -= c.real ;
imag -= c.imag ;
}
Last time, we discussed the string class besides defining the plus operator as joining the
two strings. Can we define minus for the string class? Is the minus operator relevant to
the class string? For me it does not. Unless we come with some very artificial definition.
Suppose we have a string as “This is a test” and a second string as “test”. The subtraction
of these two strings means the deletion of a word or words of second string from the first
string. It may make some sense in this example. What will happen if the second string
contains “My name is xyz”. The subtraction of these strings does not make any sense.
The thing we need to understand at this point is that every operator does not make sense
for every class. Operators should be used only when these make some common sense so
that reader can understand it easily. When you add two strings, it makes lot of sense. We
can use either cat function or write this plus operator. As subtraction of strings does not
make much sense, so it is not advisable to define it. Only define things that are selfexplanatory,
readable and understandable.

Operators with Date Class


We have so far been using the Date class. Let’s think what operators make sense for Date
class. What will be the meaning of plus operator or minus operator? Here we want to
remind you a key thing i.e. “Paying attention to detail”. Suppose you have some date and
want to add some number to it like today’s date plus 5. Does that make sense to you? We
will get a new date by adding five to today’s date i.e. date after five days. Similarly, if we
want to subtract, say 10 from today’s date, we should get the date of ten days before.
Here is the usage of plus and minus which makes some sense. Can we subtract two dates
together like subtraction of 1st Jan. 2002 from 15th Oct. 2002. What meaning it will
convey? Perhaps nothing.
Let’s consider the addition of a number to a date. Adding an integer to some date,
according to the definition we will get some date in the future. The Date object will be
returned from this function. We need a new date after the addition of integer number. We
are defining this as a member-function so that the Date object that is calling it, will be
passed to the function. The integer that is on the right hand side should be passed as an
argument. Therefore in the parenthesis, we will have the integer. Now let’s discuss it in
detail. How can we add an integer to some date? Let’s take today’s date. Write it in your
copy and see how can five be added to it. If you try to add a number to date, there are so
Page 406
many possibilities that can happen. Suppose, today is second day of the current month.
After adding five to it, we will get 7th of this month. That was case I. Let’s take the case
II. Today is 27th of any month. Now what will be the new date after adding five. First
thing, which is very obvious, that the month will get changed. But what will be the date
of this new month. It depends whether there are 30 days or 31 days in this month. It may
be the month of February. Is it the leap year or not? If it is non-leap year, there will be 28
days in February. Otherwise there will be 29 days. What is a leap year? There are rules to
determine whether the year is leap year or not. If the year is divisible by four, it will be
leap year. Similarly, being a century year, it may be divided by 400. Then again it is a
leap year. Now we have seen that there are many cases when we are adding five to 27th of
any month. Two things happen. The month is changed and the date changes according to
the days in the month. What if it is the 27th of the December? Now you want to add five
days. There are 31 days in December, after adding five it will be 1st of next month. We
may have declared an array of twelve months. As December is the twelfth month, the last
month of the year, so we have to go to first month of the next year. Here the year has also
changed. We will also need to increment 1 to year too. It seems very simple that we have
to add an integer number of days to some date. It becomes a complex function. Now
suppose we have written this complex function and embedded all the rules in it. Then our
life will become much easier. Suppose our semester starts from any date. After adding the
period of semester, we will get the end date of the semester. We can do date arithmetic.
This is a classic example of “paying attention to detail”. To use the class for general
purposes, we cannot miss even a single case. If you want to publish this class for others
to use, you need to pay attention to detail and make sure that your class handles all of the
stuff.
Here is the complete code of the program.
File “Date.h”
// The Date class is defined here
class Date{
private:
int day;
int month;
int year;
int daysOfMonth(Date d); // returns the no of days in a month
static const int daysInMonth[]; // array containing the 12 month’s days
bool leapYear(int); // tells the year is leap year or not
public:
Date(int d = 1, int m = 1, int y = 1900); // constructor with default arguments
void setDate(int, int, int); // set the date with given
arguments
void display(); // Display the date on the screen
// operators prototypes
Date operator ++ (); // pre increment operator used as ++date1
Date operator + (int); // Plus operator used as date1 + 5
Page 407
};
// The implementation of the date class.
// initializing the no of days, take 0 for month zero.
const int Date::daysInMonth[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// Displaying the function on the screen
void Date::display()
{
cout <<"\nDate:" << day << "-" << month << "-" << year;
}
//constructor of the date
Date::Date(int d, int m, int y)
{
setDate(d, m, y);
}
// setting the date as given arguments
void Date::setDate(int d, int m, int y)
{
year = y;
// if month is wrong then set it to 1
if (month < 1 && month > 12)
month = 1;
else
month = m;
// if day is wrong then set it to 1
if (month == 2 && leapYear(y))
if (d >=1 && d <=29)
day = d;
else
day = 1;
else
if( d >= 1 && d <= daysInMonth[month])
day = d;
else
day = 1;
}
// This function return the number of days in a month
int Date::daysOfMonth(Date d)
{
if (d.month == 2 && leapYear(d.year)) // if leap year then Feb is 29
return 29;
else
Page 408
return daysInMonth[d.month];
}
// Testing that the year is leap or not.
bool Date::leapYear(int y)
{
if ( (y%400 == 0) || (y%100 != 0 && y%4 == 0))
return true;
else
return false;
}
// + operator overloaded for the date. Used as date1 + 5
Date Date::operator + (int numberOfDays)
{
for (int i = 1; i <= numberOfDays; i++)
{
++(*this); // calling the pre increment operator
}
return *this;
}
// Pre increment operator
Date Date::operator ++ ()
{
if (day == daysOfMonth(*this) && month == 12) // end year
{
day = 1;
month = 1;
++year;
}
else if(day == daysOfMonth(*this)) // end month
{
day = 1;
++month;
}
else // not the last day of the month
{
day++;
}
}
The main program is:
#include <iostream.h>
#include "date.h"
Page 409
void main()
{
Date d1 (26, 12, 2002), d2(28,2 ,2000), d3;
d1.display();
++d1;
cout << "\nAfter adding 1 day, the date is ";
d1.display();
cout << endl;
d2.display();
d2 = d2 + 5;
cout << "\nAfter adding 5 days to the above date";
d2.display();
}
Output of the program:
Date:26-12-2002
After adding 1 day, the date is
Date:27-12-2002
Date:28-2-2000
After adding 5 days to the above date
Date:4-3-2000
Similarly we may have a counter-function that subtracts some number from the date. This
is the same but of reverse nature. Suppose it is Jan 3rd and we have to subtract ten days
from it. The month will be changed to December while the year is going to be
decremented by 1. To determine the date of December, we need to know the number of
days in December and count backwards. Now we don’t need the number of days of
current month. Rather the number of days in previous month is important. Suppose it is
3rd of March and subtract seven from it. What will be the date? Now you have to do
complex arithmetic and take care of all the cases. It is very complicated but having only
one time effort. Date arithmetic is very important and common in business applications.
If someone applies for vacations, you just have to enter that this person is going on leave
from this date for ten days and you will know his date of re-joining the duty. If someone
works on daily wages and paid after a week. Someday, he comes and says that he is
going on vacations. We need to calculate the number of days from the day of last
payment to to-date. It is simple date arithmetic. Writing a Date class with these
appropriate operators overloaded will be very useful exercise. It adds to your overall
programming vocabulary.
There are two kinds of programming vocabulary. One is the keywords of C/C++ etc
while the second is higher-level vocabulary. What sort of vocabulary we have in our toolbox.
In the first part of this course, we have learned how to write loops, nested loops etc.
We learn to handle matrices and vectors using those rudimentary rules. Now if you think
about that we have written a matrix class and a member function inverseOfMatrix(). We
Page 410
can use this function again and again. Similarly in the Date class, we can put in some
rudimentary calculations on date arithmetic. Add or subtract number of days from some
date. These are very useful functions. In the daily wages example, you need to subtract a
date from a date. Now we need to overload the minus operator again with date minus
date. First we overload the minus operator with date minus some integer number. There
may be two versions of minus operator. Here, you have to work in detail. Subtracting a
date from another date is relatively non-trivial. As a programming idea, you can think
that subtracting two dates involves huge calculations. Can we perform some logical tests
here? If we want to implement date1 – date2 while date1 is smaller than date2. The first
question is do we want to return a negative number. Let’s say we want this, then date1 –
date2
can return a negative number. So it can return a negative number or zero (if the
dates are identical) or positive number (the number of days). How we can implement this
functionality? One way to do it is with the help of calendar. Under this method, we will
start a loop till the other date is got. Then by reading the loop counter, we can tell the
difference in days. It is a good idea. But for that, we need a calendar somewhere. If the
dates are in different years, we will have to ensure the availability of calendar of next
year. Think about it and try to write this function.
Now what about the plus-operator for two dates? Minus operator for strings did not make
a lot of sense. Similarly, the plus operator for two dates does not make much sense. We
can add some number to date. But how can we add a date to some other date. There is no
logical and straight forward answer to this. So we don’t define such a function. The
meaning of our operator should be obvious. You can write whatever you want in the
function. But it is bad idea. The idea of this exercise is to pay attention to detail. Think of
all the various things that can happen. Tabulate them, determine the logic and then start
programming. Don’t start typing your program before your brain has come up to the
same point. First analyze the problem, understand it, look at all the cases, draw a flow
chart, write pseudo code. Once you are comfortable with this and know what you want to
do then start writing your program. The time spending on analyses is arguably the best
usage of your time as a programmer. The time you spend on debugging and removing
errors from faulty code is huge. Spending time on good design pays off. You should
debug for syntax errors like a semi-colon is missing somewhere. You should not face any
logical error at debugging stage because logic errors are very hard to track. You may just
not worry about the design and start writing code. The program may work for two or
three cases. You may declare that you have written the program. When other starts using
it on some other case which you did not cater, the program does not work or produces
some strange results. There is no syntax error in the program. The compiler compiles it
successfully and makes an executable file. Now we have to check the logic. Determining
the logic from the code is a million times more difficult than determining code from
logic. In this case, analysis will be always followed by design and then code. Please keep
this in mind.

Unary Operators


Let’s talk about unary operators. Unary operators take one argument like i++ or i--(Post
Increment or post decrement operators for integers) or ++i, --i (Pre increment or pre
Page 411
decrement operator). You can’t make unary operator as binary operator or binary
operator as unary. Let’s overload unary operator in the Date class. We want to overload
++. This operator should add a day in the current date. When we say ++date1 or
date1++
, it should get tomorrow’s date. This is same as date1 +=1 or date1 = date1 + 1.
We simply have to change to tomorrow’s date. If this is the member function, it will get
the date object automatically. The internal structure of the object is available to the
function so that it takes no argument. It will return a Date object. Its prototype will be as:
Date operator ++ ( ); // pre increment operator
What will be in the function definition? You have to pay attention to details. The
argument that we used in the plus operator, is also applicable here. What will be the next
date when we add 1 to the current date. Let’s work it out. If it is not the last date of the
month, then simply add one to the day. If the date is the last day of the month, then
change the month and date to 1st. If the date is the last date of the year, then increment the
year too. Suppose we have some function available which returns the days of month
given the month number. So if we say daysOfMonth(6) it should return 30. The function
is intelligent enough that when we say daysOfMonth(2) it should return 28 if the year is
not leap year. Otherwise, it will be 29. Therefore we have to send it year too along with
the month number. We can also pass it the complete Date structure as
daysOfMonth(date1);
We will use this function in writing the ++ operator. In a way, the
logic is same as we used in the plus operator. Suppose the object d is calling this ++
operator as d++ where d is an object of type Date. Therefore the day, month and year
data members will be available to this function. In the body of the function, first of all we
will check whether this is the last date of the month as:
if (day == daysOfMonth ( *this ) )
{
// this is the last day of the month
// process accordingly
}
In the above condition, we have checked that day is equal to the number of days in the
month or not. If the condition returns true it means that this is the last day of the month.
Here we have used this to pass the object (current object) to the function daysOfMonth.
this’ pointer is implicitly available to every member function and this pointer points to
the current object. As per requirement of the program, we have written d++ where d is
the object of type Date. We are not using the object d in the program. This object is itself
available.
Now the data of object d is available in the function as day, month or year. The object d
is itself present either from its member data (day, month, year) or through the ‘this
pointer’ which points to the current object. We can also expand the definition of the
function daysOfMonth( ) as daysOfMonth(int day, int month, int year). If the given day is
the last day of the month, we will increment the month. Before doing this, we need to
Page 412
check whether this is the last month or not. Therefore we have to introduce another
nested ‘if’ condition. The code segment will now be as:
if (day == daysOfMonth ( this ) )
{
// this is the last day of the month
if (month < 12)
{
day = 1;
month++;
}
else // this is the last month i.e. December
{
day = 1;
month = 1;
year++;
}
}
else // not the last day of the month
{
day++;
}
The ++ operator simply adds one to the date of the calling object. We define it as member
function. Therefore, no argument is needed. We can make it non-member but have to
pass it a Date object.
To distinguish the pre increment operator with post increment operator, an int argument
is passed to it. The prototype of post increment operator for Date is:
Date operator ++ (int ); // post increment operator
Here we don’t need to use this int argument. The implementation is same as pre
increment operator as in both cases we want to add 1 to the date.
Can we implement the plus operator using this function? We can write the plus operator
in some new fashion. We pass it a positive integer number, which has to be added to the
date. We can write a loop in the plus operator. The loop condition will be as i < number
where number is the argument passed to it. So in the program if we have written as
date1+5;
the loop will run for five times and in the body of the loop we have ++date1.
Suddenly our complicated logic has been boiled down to simple as incremented by 1.
This is the classic example of code reuse.
We don’t know who is going to use this code. Nobody is perfect. But we should think
before writing the program about the structure, interface, the setters and getters and the
operators to be overloaded. The thumb rule is if the meaning of + and ++ operator is
Page 413
same as in ordinary arithmetic, then + operator can be used in the ++ operator. Keep in
mind that we can call a function from another function. This is a good example of code
reuse. We can call the + operator as many times as needed. The daysOfMonth is a
member function and it is used in ++ operator function. ‘+ operator’ is a member
function, used in ++ operator. We are building a hierarchy. Suppose there is some small
logical error in the code and the daysOfMonth is not returning the correct value. This will
effect the + operator as well as ++ operator. When we remove that error, then + and ++
operator both will be corrected. Moral of the story is that whenever we write some code,
it is better to see whether we are rewriting some code in the same class. If we are
calculating the number of months at two places or determining the leap year at two
places, then try to combine this in such a way that things should be calculated at one
place. That piece of code may become some utility function. This will not be called from
outside the class so we will put this function in the private area. But the member
functions can call it. We will make the daysOfMonth() as a private member function of
the class. It will return the days of the month having checked whether this is leap year or
not. Using this utility function, we have written + and ++ operator function. Don’t repeat
code inside a class. Make it a general rule. Make a function for the repeated code and call
it where needed. For efficiency and speed, we can repeat the code. For this, we start using
macros. It means that if you put all your logic in a single place and then reuse it. You will
get lot of safety and security with this. A correction at one place will make the behavior
of the whole class correct.
Let’s see another interesting function of the Date class. Sometimes, we need to compare
two dates i.e. whether a date is greater or less than the other date. In other words, the
comparison operator is applied. Comparison operators <, >, <=, >=, == can also be
overloaded. How do we determine whether date1 is greater than date2? First of all, what
will be its return type. Return type has to be either true or false. It says date1 is greater
than date2 or date1 is not greater than date2. Let’s introduce another keyword bool. It is a
new data type. It is very simple, it only takes two values true or false. So, the return type
of greater than operator (>) is bool. The prototype of this member function is as:
bool operator > (Date d);
The argument d is the Date object that is on the right side of the greater than sign. The
left hand side Date object is available to this as this is the member operator of the class.
Before writing the code, think abut the logic. We have to determine that the calling date
is greater than the date d or not. If the year of current date is greater than date d, will the
current date greater than date d? Certainly, it will be so. If the year is greater, obviously
date is greater. If the years of both the dates are equal, then we have to check whether the
month of the current date is greater than date d or not. If the month of the current date is
greater than the date d, current date is greater. If the months are also equal, we will
compare the days. It’s a very simple hierarchical logic. To be able to write this logic
cleanly, you should write case by case on paper. Analyze it thoroughly. The logic can be
written in reverse too. If the year of the date d is greater than the current date, return false
and so on. So we can go either true, true, true or false, false, false logic. You will find the
false logic quicker. We can use if, ‘else if’ structures. Return type of this function is
Page 414
‘boolean’. Suppose that in our calling function we have two Date objects as d1 and d2.
We will write as if(d1 > d2). Why should we write this? As our operator is returning true
or false and ‘if’ also needs true or false, we can write very clean and neat code. This
greater than operator is a member operator of Date class. In this case, we have the return
type as boolean and not returning the Date object. Is it the violation of any rule? The
answer is no. The return type can be anything. It needs not to be the same as the class. It
can be anything. The same applies to difference between two dates. The difference
between two dates will be an integer. It is still a member function. It simply tells us the
number of days between two days. It could be negative or positive but it is an integer.
There is no such rule that the member operators should return the object of the same
class.
The code of the greater than operator is as follows:
// Definition of the greater than operator
bool Date :: operator > ( Date d )
{
if ( year > d.year ) // if year is greater date is greater
{
return true;
}
else if ( year == d.year) //if years are equal check month
{
if ( month > d.month ) // if month is greater date is greater
{
return true;
}
else if ( month == d.month) // if months are equal check dates
{
if(day > d.day)
return true;
else // otherwise return false
return false;
}
else
return false;
}
else
{
return false;
}
}
Now you can write all the comparison operator of the Date class. The comparison
operators are greater than, greater than or equal to, equal to, less than, less than or equal
to. If you are writing one, you might want to write all of them. Now we have expanded
Page 415
the Date class enough. As an exercise, write your own Date class. Keep in mind the
principles. What should be in the Date class? How should we set its values? How many
constructors we need? Do we need a destructor or default destructor is enough. After this,
define its public interface that is the member functions that are visible from outside. What
operators should be overloaded?
In the program, if we say date1 + 5, we know that we will get a date which is five days
later. What will happen if we write 5 + date1? The situation like this may happen. You
have published your Date class and someone wants to use it in this fashion. Here we have
an integer, the plus operator and a Date object. It should return an object of type Date. To
make this work properly, we need to have another operator. You will have to look at the
set of operators needed for this class. List them out and write down their behavior. Be
very clear what you expect them to do and start writing the class. How can we implement
integer + date
? On the left hand side, we have an integer. If the integer is at the left side,
it can’t be a member function. Member function is always called by object. Here object is
not calling the function. Rather integer is calling. So it has to be a friend function that is
sitting outside. It will get two arguments, integer and Date. As this is the friend function,
the internal structure of the Date will be available to it. You will create a new Date object
based on the given Date object and the integer and return it. We have seen that member
functions are returning integers or Boolean. Here, a non-member function is returning an
object of Date class. When we have listed out comprehensively that what will be the
interface of our class. Which functions and operators will be visible from outside? When
we have written the behavior of our class on paper, it is good to start writing the code.
You may have to write a lot of code for this class. Once we have compiled the code and
have object file, then anyone can use Date object. There will be no problem. We will
include the “date.h” file in the program and use and manipulate the Date objects. We can
use its operators, member functions etc very easily. The effort we put in writing this code
does not go waste. It will provide a lot of ease in the main program. The biggest
advantage is the encapsulation that has happened. All of the logic that was needed to
manipulate the object of class Date is now encapsulated in that class. In case of any
problem in the behavior of the class, we will need to correct the class, compile it. In the
conventional function programming or structured programming, this logic has been split
at different locations of the program. It was everywhere. Different things have been
embedded at different points. In the function oriented programming, we have written a lot
of functions at different locations. Here we have a new data type as Date. All the date
related functions are at one place. We are encapsulating all the functionalities in the Date
class that is another reason for doing all of the homework, all the thinking before we
write the code. No one can determine all the usage of the Date class. If you start
determining all the usage of Date class and writing the definition of the Date class for the
last six months, this will be impractical. You would want to keep it within limits but do
the homework then you write it. Now you can reuse it as many times as you want.
We need a friend operator when the driving thing is not the object of the class like integer
+ date
. The operator is derived by integer. Here, we use a friend function. There are
Page 416
instances where friend operators are used to manipulate two different classes. A classic
example in the mathematics is of the multiplication of vector and matrix. If we have to
multiply a vector with a matrix, the multiplication operator will be friend of both the
classes. It will get both vector and matrix as arguments and manipulate them. Keep in
mind that friend operators in a way can also be used to glue two classes. The
disadvantage of clubbing them together is that they become interlinked. Write your own
overloaded operators and see how they work.

<Previous Lesson

Introduction to Programming

Next Lesson>

Home

Lesson Plan

Topics

Go to Top

Copyright © 2008-2013 zainbooks All Rights Reserved
Next Lesson
Previous Lesson
Lesson Plan
Topics
Home
Go to Top