|
|||||
CS201
Introduction to Programming
Lecture
Handout
Introduction
to Programming
Lecture
No. 27
Reading
Material
Deitel
& Deitel - C++ How to
Program
Chapter.
6
6.9,
6.10, 6.11, 6.12, 6.13,
6.14
Summary
1)
Classes
And Objects
2)
Constructors
3)
Types of
Constructors
4)
Utility
Functions
5)
Destructors
Classes
and Objects
This
lecture is a sequel of the previous
discussion on 'Classes' and
'Objects'. The use of
'classes
and objects' has changed
our way of thinking. Instead
of having function-oriented
programs
i.e. getting data and performing
functions with it, we have
now data that
knows
how to
manipulate itself. This way,
now the programming is
object-oriented. It means
that
our programs revolve around
data and the objects.
Therefore, it would be nice
to
have
some building blocks for
programs so that these can
be combined to write a
program.
We have so far talked about simple
variables like integer,
double and char,
followed
by strings of characters and
arrays of different data
types. But now, in the
form
of an object, we
have a block which knows
itself about contents and
the behavior. The
upcoming
discussion will further explain
it. We have used cout
for
displaying many
things
like integers, doubles and
strings. Here integer did
not know how it is going
to
display
itself. However, cout
knows
how to display an integer on the
screen. Now we
want to
see that an integer should
know how to display itself. So it
will be a different
process.
Now the question arises
whether it will be good to see an
integer knowing how
to
display itself? For this
purpose, we will have to
expand the scope of
thinking.
While
engaged in the process of
programming, we try to solve a
real-world problem. The
real
world is not only of
integers, floats, doubles and
chars, but there are
other things like
cycles,
cars, buildings, schools and
people. We perceive all
these things as objects.
Each
object
has a behavior associated
with it. Consider the
example of a man who can
talk,
walk,
sit and stand etc.
Similarly, we can think of a
vehicle that has many
functions.
Page
336
CS201
Introduction to Programming
These
objects also have
attributes. For example, a man
has height, weight, color of
eyes
and hair
and so on. These all
are his attributes. His
actions will be referred as functions
or
methods.
This principle may be applicable to
vehicles, aero planes and
all other real-
world
things. An aero plane has
attributes like its height,
width, number of seats
and
number of
engines etc. These are
attributes called data members.
Its actions include
takeoff,
flying and landing. These
actions are its functions or
methods.
In terms
of language, the attributes
and actions may be equated
with nouns and
verbs.
The
verbs are actions which
are also called methods in
the programming
terminology.
These
methods should be included in the object
in such a way that the
object itself knows
how to
achieve this function or
method. Now consider this
all in terms of data. Is
it
always in
terms of salary, payroll,
amount and numbers?
Actually, data comes
in
different
varieties. Now a day, a computer is
multimedia equipment. We see that
there are
not
only alphabets and digits
displayed on the screen, but
also pictures, images,
windows,
dialogue
boxes, color and so many
other things. These are
numbers, letters and
graphics.
Other
than this, we can see videos
on our computer. It is just
another type of media.
Similarly,
we find audio material, which
can be played on the computer.
Thus in the
expanded
terms of data, we come
across numbers, pictures,
audio and video while
dealing
with multimedia.
Now we
think about the concept
that an integer should know
how to display itself.
With
the
enhanced scope of data, we
can also have an audio,
which knows how to play
itself.
The
same applies to video.
Class
A class
is a way of defining a user-defined
data type. In a class, one
may find data
members
and functions that can manipulate
that data. In the previous
lectures, we have
talked
about the concept of data
hiding i.e. encapsulation that
means that the data of
a
class
cannot be accessed from
outside. However, it can be
done through some
defined
functions
(methods). These are the
member functions of the class. To hide
the data, we
declare
it private. If a
data is private, it will be available
only to member functions of the
class. No
other function outside the
class (except friend functions) can
access the private
data.
Normally in a class we divide
the private part which is
normally what we called
implementation
of the class, from the
functions that manipulate that private
data which is
called
the interface (which is the
front end).
The
example of a room can help us
understand private and public
parts of a class. A
class
is a room
having a curtain in its middle. The
things behind the curtain (private) are
visible
to the
residents (insiders) of the room. They
know about every thing
present in the room.
When the
door opens, the outsiders
see only the things in front
of the curtain. This is
the
public
interface of the class while
behind the curtain is the private
interface. A function
inside
the class (i.e. a member function)
can access and manipulate
all things in the
class.
A
function outside the class
can only access and
manipulate its public interface
part. A
constructor
has to be in the public
section of the class. There
should also be a
public
interface
so that it can be called from
outside.
Page
337
CS201
Introduction to Programming
Constructors
Constructor
is a special function, called whenever we
instantiate an object of a class.
If
we do not
define a constructor function in a class,
the C++ provides a default
constructor.
It is
executed at the time of instantiating an
object.
To
understand the basic
function of constructor, we have to go
back. While writing
c++
Stroustrup
noticed that the majority of
programming problems, which we call
bugs, occur
due to
the use of uninitialized
data. That is, we declare
variables and use them
without
providing
them any value. For example, we
declare an integer as int
i ; And it is
not
initialized
with a value like i= 0; or i = 5;
And
then somewhere in the
program, we write,
say,
j = 2 * i
;.
This is the usage of an
uninitialized data variable. This
technique has a
demerit
that despite having no syntax error, it
may cause a logical error,
which is difficult
to find.
Thus, initialization of data is a
very critical activity. The
constructors give us an
opportunity
to initialize the data
members of an object in such a way
that when our
program
gets an object, the data
part of the object is in a known
state. Being in a
valid
state, it
can be used. The
constructors are used to
initialize the data members
of an object.
A class
is a user defined data type it
does not take space in
the memory unless we
create
an object
from it. The constructors
create space for data
members and put values in
them.
We want
these values to be there
when an object is instantiated. Thus
initialization is a
good
reason for using
constructors.
Types
of Constructors
Compiler
Generated Constructor
If a
constructor is not defined by the
use the compiler generates
it automatically. This
constructor
has no parameter. It does nothing.
Although the compiler will
create a default
constructor
for us, the behavior of
the compiler-synthesized constructor is rarely
what we
want.
Thus the default constructor provided by
the compiler does no
initialization for
us.
Simple
Constructor
We have
earlier discussed that we
can write a constructor that
takes no argument.
The
user
defined constructor, that takes no
argument is called a simple constructor.
We know
that
when a compiler generated default
constructor is called, it does no
initialization. It
does
not know whether to put a value in
data members like day,
month in our previous
class
Date. We can
avoid this problem by not writing a
class without having
its
constructor.
A simple
constructor can do initialization
without any need to take
any argument. So we
can
write a constructor of Date
class
like Date
();. When we
write such a constructor,
it
automatically
assumes the roll of the
default-constructor. The compiler will
not call the
default
constructor. Rather, the
constructor written by the programmer
will be called
whenever
an object will be instantiated. It is
also a good programming
practice to provide
a default
constructor (i.e. a constructor wit no
argument).
Parameterized
constructors
We may
define a constructor, which takes
arguments as well. This
constructor will be
automatically
called when the required
number of arguments are
passed to it. Through
Page
338
CS201
Introduction to Programming
this, we
can easily assign the passed
values to our class data
members for that
particular
object.
In our
previous example of class Date,
we
have written a constructor as
follows
Date
(int, int, int);
This is a
parameterized constructor which
takes three arguments of type
int.
Constructor
Overloading
We can
provide more than one constructors by
using function overloading. The
rules for
function
overloading are that the
name of the function remains
the same. However,
its
argument
list may be different. There
are two ways to change
the argument list. It
can
either
vary in the number or type of
the arguments. We cannot
have two functions
with
the
same number and type of
arguments. In such a case,
these will be identical. So it
will
not be
function overloading. The function
overloading requires the argument
list to be
different.
The same concept of function
overloading applies to constructors. If we
supply
more than
one constructor for a class,
it can be called one or the
other depending on
the
way of
calling.
As the
constructor does not return
any thing, so it has no
return type. It means that
the
body of
the construct function
cannot have any return
statement. Otherwise, the
compiler
will
give a syntax error.
Explanation
of Constructors
The
main purpose of the
constructor is to initialize the object
in such a manner that it is
in
a known
valid state. Consider the
example of Date
class
again. In that example,
there
were
three data members i.e. day,
month and year of type int.
What values will we give
to
these
data variables by default if we create an
object of Date? There
may be any valid
date. We
can give a value 01 to day,
month and 1901 to year or
what ever we want. It
will be a
known state despite being
meaningless. We can write a
constructor of class
Date
which
takes three arguments int
day, int month and
int year, and puts
values in the
data
members of the object, being
created. Now the question
arises when does
this
happen?
It happens when we instanciate an object
of class Date
by
writing Date
myDate;
When
this line executes in the
program, some space for 'myDate' is
reserved in
the
memory. This space contains
the space for day, month
and year variables.
Then
control
goes to the constructor that
assigns values to day, month
and year. Being a
member of
the class, the constructor
can write values to the
data members of the
class
that is
private. .
In C++
language, we can provide default
arguments to functions. As a function,
the
constructor
can take default arguments.
Suppose we have written a
constructor of class
date
with the arguments by
providing default values to its
arguments. We can write
a
constructor
as
Date
(int day=1, int month=1, int
year=1);
and
create an object of class Date
as
Date
myDate;
This
creates an object of type Date. Which
constructor will be called? A
constructor with
no
arguments or the parameterized
constructor in which each
argument has given a
value? If
we provide a constructor which has
default values for all the
arguments, it will
become
the default constructor for
the class. Two constructors
cannot be considered
Page
339
CS201
Introduction to Programming
same. So
it will be better not to
write a constructor Date ();
(constructor with no
argument)
in case of providing a fully
qualified constructor (with default
values for all
arguments).
Now
suppose, we want to initialize
the Date
object properly by
passing a character string
to its
constructor. Is it possible to write
such a constructor? Yes, we can
write such a
constructor.
This constructor will take
date as a string, say, 01-jan-1999.
And in the
constructor,
we can split up this string with 'string
manipulation functions' and
assign
respective
values to day, month and
year.
Now we
recapture the concept of
constructors with special
reference to their
characteristics.
A
constructor is a function which
has the same name as
the class.
It has no
return type, so it contains no return
statement.
Whenever
an instance of a class comes
into scope, the constructor
is executed.
The
constructors can be overloaded. We
can write as many constructors as we
require.
At one
time, the compiler will
call the correct version of
the constructor".
Utility
Functions
The
second issue, we usually
come across while dealing
with the concepts of
'classes and
objects'
is that a class has a data
on one side (normally private
part) and functions on
the
other
(normally public part). The
functions (methods) are normally
written in public
part
of the
class. Are there functions
which are private to a class?
Answer is yes. The
functions of a
class may be of two
categories. One category
contains the member
functions
which manipulate the data or extract
the data and display it.
Through these, we
can
set and get values to
manipulate data. These are
the functions which are in
public
interface
of the class and manipulate
the data in the object. But
sometimes, we need
such
functions
that is the requirement of
these member functions. Suppose we write
a setDate
function.
This function is given an argument
and it does the same
thing as done by the
constructor.
In other words, it sets a value of
date. Now that function
can be public so
that it
can be called from outside
the class. Now we want
that the member functions of
the
class can call this
function. But it should not
be called from outside. In this
case, we
put this
function in private section of the
class. These functions are called
utility
functions.
These are a utility used by
other methods of the class.
However, they are
not
functions,
supposed to be accessed from
outside the class. So they
are kept private.
Destructors
The
name of the destructor is
the same as that of a class
with a preceding tilde sign
(~).
The ~
and name of the class is
written as a single word without
any space between
them.
So the
name of the destructor of
class Date
will be
~Date. The
destructor can not be
overloaded.
This means that there
will be only one destructor
for a class.
A
destructor is automatically called when
an object is destroyed. When does an
object
gets
destroyed? When we create an object in a
function, this is local to
that function.
When the
function exits the life of
the object also comes to
end. It means that the
object
is also
destroyed. What happens if we
declare an object in the main
program? When the
main
program ends, its objects
also comes to end and
the destructor will be
called.
Page
340
CS201
Introduction to Programming
The
destructor is normally used
for memory manipulation
purposes. Suppose we
have
such a
class that when we create an
object of it then its constructor
has allocated some
memory.
As we know that we have to
free the allocated memory to
ensure its
utilization
for
some other program. The
destructor is used normally
for this purpose to make
sure
that
any allocated memory is
de-allocated and returned to
free store (heap).
The
destructors can be summarized as the
following.
The
destructors cannot be
overloaded.
The
destructors take no
arguments.
The
destructors don't return a
value. So they don't have a
return type and no
return
statement
in the body.
Now we
come to the previously
defined class Date.
Let's
see what can we further put
in
it. We
have put in it constructors. We
have provided a parameterized constructor
without
default
arguments. So the constructor
with no arguments will
become default one. We
have
another constructor with
three parameters so that we
can pass it the values
for day,
month
and year. There is also
provided a destructor. We have written
some methods to
set
day, month and year.
These were setDay,
setMonth and
setYear
respectively.
Each
one of
them takes one parameter, a
simple integer. Then we have
get functions. The
functions
getDay, getMonth
and
getYear
return a
simple integer. There is
also a
function
setDate,
which
takes three parameters (i.e.
day, month and year)
and sets them.
In set
function, we do not simply
assign the values to the
data members. This can be
done
through a
constructor. Whenever we put
data into an object, it is necessary to
make it sure
that
valid values should be
stored. For example, if we say
Date
myDate ; and
give it
values
like 35 for day, 13 for
month and 2000 for
year. The constructor will
set these
values.
But these are invalid
values for a date. Here we
want that these values
should be
validated
before being assigned to
data members. So we write
some code for
error
checking of
the values and store
only valid values in data
members i.e. day, month
and
year. We
do the same thing in set
function. Then what is the
advantage of using
set
functions.
The set functions are public
part of the class and
can be called from outside
the
class
and also by the constructor.
So write all the code
for error checking and to
validate
the
data in set function and
call this set function in
the constructor. Thus when
we create
an object of
class date, it is written as
the following
Date
myDate (12,10,2000);
Then an
object of Date
class is
created and the constructor
of the class that takes
three
arguments,
is executed by passing these
three values. In the
constructor, we call the
set
function
which sets the values of
the data members properly.
Thus we get a fine
initialization
of the data members.
What an
Object is ? An object is an instance of a class. When
we say an instance
that
means
that this object exists and
takes space in the memory.
What happens when we
create an
object i.e. take an instance of the
class. A class contains data
and methods. Are
these
methods reproduced for every
object? Every object has
data of its own as
every
object is
distinct from the other.
For example, in case of the
date class, there may
be
objects
date1, date2 and date3.
These are three different
objects having their own value of
Page
341
CS201
Introduction to Programming
date.
Being distinct objects, they
must have distinct space in
memory. What about
functions inside
the class?
Whenever
we create an object of a class, the
functions of the class take a
space in the
memory
and remain there. There is
only one copy of these functions in
the memory. The
data
part of the class takes
individual locations in the memory. So if
we create three
objects
of a class, say date, there
will be one copy of the functions in
the memory at the
time of
execution of the program. The
data will have allocated
three spaces in the
memory
with different values. Now
suppose, we want to change
the data of date1,
there
is need
of setting month of date1 to 3. So we
call setMonth
function
for the object date1.
We use
dot operator (.) to call the
function of an object. We write this
as
date1.setMonth(3);
The
setMonth
function
is called from the copy of the functions
that
is in the
memory. The object name with
dot operator makes sure
that the function
will
operate
on the data of that object.
Thus only the value of
the month of date1 will be
set to
3. The
values of date2 and date3
will remain untouched. Similarly if we
say
date2.setDay(23);
the
setDay
function
will be called for object date2
and day of date2
will be
set to 23. Thus it is clear
that which object calls the
function the data of that
object
is
visible to the function and
it manipulates only that
data. Thus we have not
wasted the
memory by
making separate copy of the functions
for each object. All objects of
one
class
share the common functions. On
the other hand, every object
has its own data
space.
The
overloaded functions and constructors
are also found in this single copy
and called
whenever
needed. In the overloaded functions,
the appropriate function to be called
is
resolved
by the parameter list (type
and number of the arguments
to be passed).
In our
class Date,
we
need no functionality for
the destructor. We write the
destructor
~Date
and a
cout statement in it. That
displays the message `The object
has destroyed'
just to
demonstrate the execution of the
destructor. Similarly we can display a
message
like
`Date object created' in our
constructor function. By this, we can
see when the
constructor
is called. By seeing these messages on
the screen we know that
the object is
being
created and destroyed properly. If
the constructor function is
overloaded, we can
put
appropriate message in each
constructor to know which
constructor is called while
creating
an object. For example in default constructor, we
can display a message
`Default
constructor
is called'.
The
following program demonstrates the
execution of constructors and
destructors. It is
the
previous example of Date class. It
displays appropriate messages according
to the
constructor
called. You will see that
the constructor is called depending
upon the
parameter
list provided when the object is
being created.
/*
A sample
program with the Date class.
Use of constructors and destructor is
shown here.
A message
is displayed to show which one
constructor is called
*/
#include
<iostream.h>
//#include
<stdlib.h>
//
defining the Date
class
class
Date{
//
interface of the
class
Page
342
CS201
Introduction to Programming
public:
void
display();
// to display
the date on the
screen
void
setDay(int i); // setting the
day
void
setMonth(int i); // setting
the month
void
setYear(int i); // setting the
year
int
getDay();
// getting
the value of day
int
getMonth();
// getting
the value of month
int
getYear();
// getting
the value of year
//
Constructors of the
class
Date();
Date
(int, int);
Date(int,
int, int);
//
Destructor of the
class
~Date
();
// hidden
part of the class
private:
int
day, month, year;
};
//
defining the
constructor
// default
constructor. setting the date to a
default date
Date::Date()
{
day =
1;
month =
1;
year =
1900;
cout
<< "The default constructor is
called" << endl;
}
//
Constructors with two
arguments
Date::Date(int theDay,
int theMonth)
{
day =
theDay;
month =
theMonth;
year =
2002;
cout
<< "The constructor with
two arguments is called" <<
endl ;
}
//
Constructors with three
arguments
Date::Date(int theDay,
int theMonth, int
theYear)
{
day =
theDay;
month =
theMonth;
Page
343
CS201
Introduction to Programming
year =
theYear;
cout
<< "The constructor with
three arguments is called" <<
endl;
}
//Destructor
Date::~Date()
{
cout
<< "The object has destroyed"
<< endl;
}
// The
display function of the
class date
void
Date::display()
{
cout
<< "The date is " << getDay() <<
"-" << getMonth() << "-"
<< getYear() <<
endl;
}
//
setting the value of the
day
void
Date::setDay(int i)
{
day =
i;
}
//
setting the value of the
month
void
Date::setMonth(int i)
{
month =
i;
}
//
setting the value of the
year
void
Date::setYear(int i)
{
year =
i;
}
// getting
the value of the
day
int
Date::getDay()
{
return
day;
}
// getting
the value of the
month
int
Date::getMonth()
{
return
month;
}
// getting
the value of the
year
int
Date::getYear()
{
Page
344
CS201
Introduction to Programming
return
year;
}
/* Main
program. We will take three
date objects using the
three constructors
(default,
two arguments and three
arguments and display the
date.
*/
int
main()
{
Date
date1, date2(12,12), date3(25,12,2002);
// taking objects of Date
class
//
displaying the dates on the
screen
date1.display();
date2.display();
date3.display();
}
Following
is the output of the above
program.
The
default constructor is called
The
constructor with two
arguments is called
The
constructor with three
arguments is called
The
date is 1-1-1900
The
date is 12-12-2002
The
date is 25-12-2002
The
object has destroyed
The
object has destroyed
The
object has destroyed
Page
345
Table of Contents:
|
|||||