|
|||||
CS201
Introduction to Programming
Lecture
Handout
Introduction
to Programming
Lecture
No. 26
Reading
Material
Deitel
& Deitel - C++ How to
Program
Chapter.
6
6.5,
6.7, 6.8, 6.10, 6.11,
6.14
Summary
·
Classes
and Objects
·
Definition
of a class
·
Separation
of Interface from the
Implementation
·
Structure
of a class
·
Sample
program
·
Constructor
·
Default
arguments with
constructors
·
Tips
Classes
and Objects
In
today's lecture, we will try
to learn about the concepts
of `classes' and
`objects'.
However,
we are not going to formally
cover the object-oriented programming
but only
the
ways to manipulate the classes
and objects.
We had
talked about structures in our
previous lectures. In structures,
some data variables
are
gathered, grouped and named
as a single entity. Class and
structure are very
closely
related.
In classes, we group some
data variables and functions.
These functions normally
manipulate
these variables.
Before going
ahead, it is better to understand
what a class is:
"A class
includes both data members as
well as functions to manipulate that
data"
These
functions are called `member functions'. We
also call them methods. So a
class has
data
(the variables) and functions to
manipulate that data. A class is a
`user defined' data
type.
This way, we expand the
language by creating a new
data type. When we
create
variables
of a class, a special name is
used for them i.e.
Objects.
"Instances of a
class are called
objects"
Page
322
CS201
Introduction to Programming
With
the definition of class, we
have a new data type like
int, char etc. Here int
i; means
`i' is an
instance of data type int. When we
take a variable of a class, it becomes
the
instance
of that class, called object.
Definition of
a class
Let's
have a look on the structure
of a class. It is very similar to
the struct keyword.
Keyword
class is used and the
braces enclose the
definition of the class
i.e.
class
name_of_class{
//
definition of class
}
The
new data type i.e. classes
helps us to have grouped
data members and
member
functions to
manipulate the data. Consider a
structure of Date having data
members i.e.
year,
month and day. Now we can
declare a variable of structure Date
and use dot
operator
to access its members
i.e.
Date
myDate;
myDate.month=3;
We have
to use the name of the
object, a dot operator and
the data member of structure
to
be
accessed. The data members
are of normal data types
like int, float, char
etc. Other
data
types can also be
used.
Let's
consider an example of Date Class shown
in the following
statement.
class
Date{
int
Day;
int
month;
int
year;
};
Now we
will take its object in the
fashion given below:
Date
myDate;
Separation of
Interface from the
Implementation
To access
the data members of the
class, we will again use
dot operator. Before going
ahead, we
will see what is the
difference between struct and
class. It is the visibility
of
the
data members that differentiates
between struct and class.
What does the
word
`visibility'
mean? Consider an example of payroll
system. We have stored the
tax rate i.e.
5% in a variable
i
of
type int. Later, we used
the same i
in a
loop and changed the
value
of tax
rate unintentionally. Now
the calculation of the pay in
the end will not provide
the
correct
results. To avoid this problem, we can
tag the tax rate variable as
int
tax_rate;.
Page
323
CS201
Introduction to Programming
But
this variable again is visible in
the whole program and anyone
can change its
value.
The
data is open and visible to
every part of the program,
creating a big problem.
In normal
programming, we will like to see
the data encapsulated. It
means that data is
hidden
somewhere. However, it can be
used. Let's consider a real
world problem to
understand
it. Most of us have
wrist-watches. To have accuracy, it is
necessary to adjust
the
time. How can we do that? We
can change the time by
using the button that
is
provided on
one side of the watch.
This is a kind of encapsulation. We
can see the
hands
of the
watch but cannot touch
them. To change their position we
used the button.
Whenever
we talk about the class, we
have to think of this
concept that data is
available
somewhere.
We don't need to know about
the exact structure i.e. what is inside
the
watch.
All we know is that its internal
structure is defined somewhere
that cannot be seen
or
touched. We can only see
its interface. If we need to
adjust the time, a button
may be
used. It
is a nice separation of implementation
and interface. Classes allow
us to do that.
Structure of
a class
Let's
have a look inside a class.
Consider the example of class
Date. Can we set
the
values of
the data members of the
object `myDate' i.e. day, month or
year. We cannot say
like
myDate.month =
11;.
Try to do this. The compiler
will give error and
stop compiling
the
program. It will not
recognize the variable `month'. In
other words, it cannot
see
`month'.
The default visibility for
the data members of the
class is called `private'.
These
can
only be used within the
class and are not
visible outside.
"The
default visibility of all the
data members and member
function of a class is
hidden
and private"
`private'
is also a keyword. What will
be the opposite of the
private? What we will
have
to do to
use the data members
and manipulate them. The keyword
for this purpose is
public.
In the class definition, if
you do not mention the
visibility and start
defining the
data
and functions, these will be by default
private. As a good programmer, we
should
always
write the keyword private
with a colon as:
private:
Now
all the data and functions
following this statement
will have the private
visibility.
To define
the public data, we need to
write the keyword public
with a colon as:
public:
Now
all the data and functions
following the public keyword
will have the
public
visibility.
These will be visible from
outside the class. We can
have multiple public
and
private
parts in the class
definition but it becomes confusing. So
normally we have only
one
public and one private part.
Again consider the Date
example. By making the
data
members
as private, we will write functions to
set and get the
date. As this is needed to
be
visible
from outside the class,
these functions will be defined as
public.
class
Date
Page
324
CS201
Introduction to Programming
{
private:
// private
data and functions
public:
// public
data and functions
};
Normally,
the data in a class is kept
private. If we make the data
public, it is same as
structure
and anyone can access
this data. On the other
hand, the functions which
we
have
written to manipulate this data,
are kept as public. These
methods can be called
from
outside the class i.e. from
the main program. These
are the member functions of
the
class.
The difference between these
and the ordinary functions is that
they are part of
class.
Moreover, they can see the private
data members of the class
and also manipulate
them.
We have
made the data members
private in the Date class. In
the program, we take
an
object of
Date class as Data
myDate;. myDate
is a
variable of type Date. Now if we
say
myDate.month =
3; this
statement will be illegal as
the month
is a
private data member of
the
Date class. Now try to
understand this concept. You
can think class as a box
having
different
things in it. How can we
touch inside the box? We have a
window and can
see
only
those things that are
visible through this window.
Those things which we cannot
see
from
the window, can not be
accessed from outside. Day,
month and year are
somewhere
inside
the box and are
not visible through the
window. Now we want to
assign some
values to
these data members. For
this purpose, we will define a member
function in the
class in
the public section. Being
present in public section, it
will be visible through
the
window.
As this is the member function, it
can see and manipulate the
private data of the
class.
Now it's a two-step process. We
can see the public functions
and public functions
can
view the private data
members of the class. We
will write a function to set
the value
to the
month. We cannot write it as myDate.month =
10;.
So our function prototype
will
be
as:
void
setMonth(int month)
and we
may call this function
as:
myDate.setMonth(10);
Now
the function setMonth
will
assign the value 10 to month
data
member of the object
myDate. The
same thing will be applicable if we
want to print the date. We
can write a
public
function print and can
access it as:
myDate.print();
The
function print can see
the private data members. So it
will format the date
and print
it. In
structures, the data members
are public by default. It means
that these are visible
to
all
and anyone can change them.
Is there any disadvantage of
this? Think about the
date.
Page
325
CS201
Introduction to Programming
What
may be the valid values of
the day? Can we have a
day less than zero or
greater
than
32.
So the
minimum and maximum values
of the day are 1 and 31
respectively.
Similarly,
in case of month, the
minimum and maximum values
may be 1 and 12. We
can
assign
different values to year
like 1900, 2002 etc. If we
are using Date structure
instead
of a
class, we can write in the
program as myDate.month=13;
and
the month will be set
to 13. So
the date will become
invalid. We may want that
other programmers also use
this
structure.
But other programmers may
put invalid values to the
data-member as these
are
publicly
accessible. Similarly in structures,
everything is visible i.e. what are
the names
of the
data members. How are
these manipulated?
Now we
want that only those things
should be visible which we
want to show and
those
things
which we want to hide should
not be visible We can get
this by using the
private
and
public in the classes.
Public becomes the interface
of the class, what we want
to show
to
others. With the use of
public interface, the
objects can be manipulated.
Private
becomes
the inside of the class i.e.
the data members, the
implementation. We don't
want
to show
the implementation of our
classes to others. This is
the concept of separation
of
interface
from implementation. It is a crucially
important concept in
modern
programming. We
have separated the interface
from the implementation. As
long as the
interface
remains the same, the
implementation can be changed.
Let's think about it
in
real
world. The example from the
automobiles sector can help us
understand further. The
production of
cars in the world started in
the late 18th century and early 19th century. Let's
compare
these early or prototype cars with
today's modern ones. There is a
big difference
between
the old and new
cars. Technology has changed.
Now what is still common
in
both
the types. Steering, clutch,
brakes and accelerator pads
are still the basic
components
of a car.
So the interface is same.
The internal functionality can be
changed. To turn the
car,
old cars used rod
mechanisms and modern cars
have the microprocessor to do
this
job. Our
physical action is same in both the
cases. The interface i.e.
steering is same and
also
the effect that wheels have
turned to right is the same
too. The internal
implementation
has completely changed. The
old combustion engine cannot be
compared
with
the state-of-the technology based
modern engines. But the
interface is the same
i.e.
we turn
the key to start an engine.
This concept of separation of
implementation from
interface
comes into our programming.
We have written a program
today to calculate
the
orbital
time of moon around the
earth. In today's physics, we have
formula to calculate
this. We
have defined the interface
calculateOrbitalTime(). This is
a function that will
calculate
the orbital time of moon
around earth. This formula
may prove wrong
after
some
time. Now what can we
do? Despite the change in
the implementation,
interface
remains
the same i.e. the name of
the function is same. Now
when the program will
use
this
function, it gets the
correct result as we have implemented
the new formula inside
the
function.
Moreover, the main program
does not need to be changed
at all. Being a very
neat
concept, it can be used
while dealing with objects
and classes.
Sample
program
Let's
see the example of Date
class in detail.
class
Date
{
Page
326
CS201
Introduction to Programming
public:
void
display();
Date(int,
int, int);
private:
int
day, month, year;
};
Date is
the name of new user defined
data type. After the
braces, we have written
the
keyword
public. In this section, we
will define the interface of
the class. We have
declared
a function display()
which
will print the date on
the screen. Another
function
Date(int
day, int month, int year)
is
declared. The name of this
function is same as
the
name of
the class, having no return
type. This function is called
constructor. Then we
write
the keyword private and define
the implementation of the
class. Here we have
three
variables
i.e. day, month and year of
type int. In the end closing
braces and the semi-
colon.
This is
the definition of user
defined data type i.e. class. It
will not occupy any
memory
space as it has no data
currently. It is the same as we
write in case of `int'.
It
does
not occupy any memory but
when we say int
I, the
memory is reserved for i.
The
class is
a `user defined data' type. Now in
our program, when we write
Date
myDate;
an
instance
of the class is created i.e. an object.
Object reserves space in the
memory. Object
will
have these data members.
What about the `functions'?
For a moment, we can
say
that
functions are also in the
memory.
We want
to use this class in our
program and display the date
using the display()
function.
We have written the prototype of
the display()
function
in the class without
defining
the display()
function
yet. A special way is used to define
these functions. We
will
write the name of the
class, followed by two
colons and the name of
the function.
The
rest is same as we used to do
with ordinary functions.
Date::display()
{
// the
definition of the
function
cout
<< "The date is " << day
<< "-" << month << "-"
<< year << endl;
}
You
might have noted the
difference in the first line.
The double colon is called
scope
resolution
operator. It resolves the
scope and tells that
this function belongs to
whom. In
this
case, the ( Date::display()) ) tells
that the display()
function
belongs to the Date
class.
So the
scope resolution is required. In a way,
consider it as function is defined inside
the
class. If
you have private function,
even then the definition
mechanism is same. We will
define
the function outside of the
class. Even then it will
not be visible as its
visibility is
private.
The way to define the member functions
is, class name, double colon,
name of
the
function including arguments
and then the body of the
function. Can we define
the
function
inside the class? Yes we can. When we
write the function inside
the class, the
compiler
tries to treat that function as
inline function. As a good
programming practice,
we define
the functions outside of the
class. So to make sure that
the function belongs
to
the
class, the scope resolution
operator is used.
Page
327
CS201
Introduction to Programming
We have
so far tried to discuss Date class at a
rudimentary level. That is we can
create
objects
of Date class and display
the date using its
functions. We can do a lot of
other
things
with this class. When we say
int
i; and
ask to print its value.
The answer is that we
have
not assigned any value to it
yet and don't know what
will be there at that
memory
location.
Similarly, when we declare an object of
the Date class as Date
myDate;
an
object is
created. But we don't know
about the values of day,
month and year. Now if
we
call
its public function display()
using
the dot operator as myDate.display(). It will
print
whatever
the value is in the data
members. We need functions to set/change
the date.
Suppose
we want to set the day,
the month and the
year separately. For this
purpose, we
need
three more public functions. We can
name these functions as setDay(int
),
setMonth(int)
and setYear(int). These functions may be
called inside the program as
myDate.setDay(15), myDate.setMonth(12)
and
setYear(2002). These
functions will
change
the value of day, month and
year. As these are member functions, so
scope
resolution
operator is being
used.
void
Date::setDay(int i)
{
day =
i;
}
void
Date::setMonth(int i)
{
month =
i;
}
void
Date::setYear(int i)
{
year =
i;
}
The
question arises, which
objects data members are
being set. In the setDay
function,
we
are
assigning value to the day. But
this day
belongs
to which object. The answer
is, we
have
just defined the function,
it is not called yet. The functions are
called by the objects,
not by
the class. When we say Date
myDate; it
means that we have an object of
type
Date.
Now we can say myDate.setDay(10). The
value of day of myDate
object
will be set
to 10.
When we create objects, these
will reserve space in
memory. Suppose, the
objects
are
date1, date2, date3. These
will be created at different
memory locations having there
own
data members. When we call a member
function with the object
name, this function
will
manipulate the data of this object.
Let's consider the following
code snippet to
understand
it.
Date
date1, date2, date3;
//
Manipulating date1 object
date1.setDay(10);
date1.setMonth(12);
Page
328
CS201
Introduction to Programming
date1.setYear(2002);
date1.display();
//
Manipulating date2 object
date2.setDay(15);
date2.setMonth(1);
date2.setYear(2003);
date2.display();
We have
declared three objects of
type Date. All these objects
have data members
day,
month
and year. When we call a
function, that is defined in
class, with some object
name,
it uses
the data of that object
which is calling the
function. Suppose, when we
write
date1.setMonth(12);
it
will manipulate the data of object
date1.
Similarly when we say
date2.display(), the
function is defined inside the
class. However, it will use
the data of
date2
object.
Remember that we will always
call these member functions by referring
to
some
specific object. We can call
these functions with date1,
date2 or date3 respectively.
We will
never call these functions referring to a
class that is we cannot
say
Date.display();
It is
illegal. The functions of getting data
from objects and setting
data of
objects
are standard. So we normally
use the word `set'
for setting the data
and `get' for
getting
the data. It is a matter of style.
You can call it whatever you
want. But it will be
a
bad
idea to name a function
print() and it is setting
the value of month. It will
work but in
a very
confused manner. If we want to
write a function to set month,
the logical choice of
the
function name is setMonth(int).
Similarly, setDay(int)
and
setYear(int)
will be
used to
set
the day and year
respectively. If we want to get the
values of these data
members, the
logical
choice will be getDay(),
getMonth() and
getYear(). The
names are self-
explanatory.
These functions are defined as member
functions of the class. They
are put
in the
public section of the class
and constitute the public
interface of the class.
These
will be
visible from outside the
class. Normally they manipulate
the data that is
hidden
inside
the class i.e. in the private
section of the class. No
need to show the working of
the
functions
only its name, argument
and the return type is told
to the user. User of the
class
is our
program.
Here is
the complete code of the
Date class.
/* A
sample program with the Date
class. Set methods are given
to set the day, month
and
year.The
date is also diplayed on the
screen using member function.
*/
#include
<iostream.h>
//
defining the Date
class
class
Date{
//
interface of the
class
public:
void
display();
// to display
the date on the
screen
void
setDay(int i); // setting the
day
void
setMonth(int i); // setting
the month
Page
329
CS201
Introduction to Programming
void
setYear(int i); // setting the
year
// hidden
part of the class
private:
int
day, month, year;
};
// The
display function of the
class date
void
Date::display()
{
cout
<< "The date is " << day
<< "-" << month << "-" <<
year << 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;
}
// Main
program. We will take two
date objects, set day,
month, year and display the
date.
int
main()
{
Date
date1,date2; // taking objects of
Date class
//
setting the values and
displaying
date1.setDay(1);
date1.setMonth(1);
date1.setYear(2000);
date1.display();
//
setting the values and
displaying
date1.setDay(10);
date1.setMonth(12);
date1.setYear(2002);
date1.display();
}
Page
330
CS201
Introduction to Programming
The
output of the program is:
The
date is 1-1-2000
The
date is 10-12-2002
Constructors
We have
written a function named Date(int,
int, int) in our
class. This is in the
public
section
of our class. It has no
return type, having the name
as that of class. Such
functions
are
called constructors. When we create an object by
writing Date
myDate; A
function is
invisibly
called which does something with
this object. This function is
constructor. If we
do not
write a constructor, C++
writes a default constructor for
us. By and large, we
want
that
the object should be created in a
certain state. When our object
myDate
is
created its
data
members-day, month and year
have some value. We
can initialize these
data
members
with zero or with some
specific date. How can we do
that? Native data
types
can be
initialized as:
int
i;
i =
10;
OR
int i =
10;
Generally, a
constructor initializes the object
into a state that is recognizable
and
acceptable.
The default constructor does
not take any parameter. We
can have many
constructors
of a class by overloading them. The
constructor for Date class
is:
Date(int,
int, int);
This is
the prototype of the constructor
that is defined in the class.
The definition of
constructor
is same as we used with the
member functions.
Date::Date(int theDay,
int theMonth, int
theYear)
{
day =
theDay;
month =
theMonth;
year =
theYear;
}
How
can we call this
constructor? We know that
constructor is automatically called
when
an object is
created. To use this
constructor, we will take an object
as:
Date
myDate(1, 1 , 2003);
Here two
things have taken place. 1) An object is
created 2) The data members
are
initialized.
This is happening in the
memory at run time. Nothing
will happen at
compile
time.
The constructor will be called
after the object creation
and before the control
given
back to
the program. Here the value
of day of the myDate
object is 1,
the value of month
Page
331
CS201
Introduction to Programming
is 1 and
the value of year is 2003.
It has created and
initialized an object. Now if we
call
the
display()
function.
These values will be
displayed. Constructor is used to
initialized
an object
and put it into a consistent
and valid state.
Default
arguments with
constructors
We can
also use the default
arguments with the
constructors. In the case of
Date,
normally
the days and months are
changing and the year
remains same for one
year. So
we can
give the default value to
year.
Date::Date(int theDay,
int theMonth, int theYear =
2002)
{
// The
body of the constructor
}
Now we
have different ways of
creating objects of class
Date.
Date
myDate;
In this
case, the default constructor
will be called while the
data members remain
un-
initialized.
Date
myDate(1, 1, 2000);
The
constructor will be called and
initialized. The day will be
1, month will be 1 and
the
year
will be 2000.
Date
myDate(1, 1);
The
constructor will be called and
initialized. The day will be
1, month will be 1 and
the
year
will be initialized to the default
value i.e. 2002.
There
are some complications.
Constructor is itself a function of
C++ and can be
overloaded.
We can have many constructors.
Suppose, we are asked to
write the date i.e.
1, 1,
2000. Some of us may write
it as 1, 1, 2000. Some will
write it as 1/1/2000. A
considerable
number may write as
1-1-2000. One can write
date as 1 Jan. 2000.
There
may
have many formats of dates. It will be
nice if we can initialize the object
using any
of these
formats. So we may have a constructor
which takes a character string.
The date
format is
'01-Jan-2003'. So the constructor
should parse the string. The
string before the
hyphen is
day (i.e. 01) convert it
into an integer and assign
it to day. Again get the
strings
before
the 2nd
hyphen (i.e.
Jan), check which month is
it (i.e. 1) and assign it to
month.
Rest of
the string is year so convert it
into integer and assign it
to year. We are doing a
lot
of
horizontal integration here. The
good thing is that the
rules of simple functions
overloading
applies to constructors also.
The rules of default arguments
also apply while
we are
using default arguments with
constructors. The idea is to
make the class as
friendly
as possible for the users.
We have two constructors. Of
these, one takes three
ints
and
the other takes the
date as a character string. We may
want to add more
constructors.
Page
332
CS201
Introduction to Programming
But we
don't want to add too
many constructors in the
class as there is a limit
of
everything.
Within limits and the
reasons, provision of two to
three alternatives to
the
users of
the class for object
creation is nice. May be the
program that is using our
class, is
applying
months as character strings. We should
provide a constructor that deals
with
this. We
will further explain this
subject in the coming
lectures. A constructor is a
special
kind of
function having same name as
that of a class. It has no
return type. Declare
it
without
return type. Constructor can take
arguments. The default constructor
takes no
argument.
Here is
the code of the Date
class using the different
constructors.
/*
A sample
program with the Date class.
Use of constructors is shown here.
*/
#include
<iostream.h>
//#include
<stdlib.h>
//
defining the Date
class
class
Date{
//
interface of the
class
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, int);
// 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;
Page
333
CS201
Introduction to Programming
}
//
Constructors with default
arguments
Date::Date(int theDay,
int theMonth, int theYear =
2002)
{
day =
theDay;
month =
theMonth;
year =
theYear;
}
// 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;
}
Page
334
CS201
Introduction to Programming
// getting
the value of the
year
int
Date::getYear()
{
return
year;
}
// Main
program. We will take three
date objects using
constructors, and display
the date.
int
main()
{
Date
date1, date2(1, 1, 2000),
date3(10,12); // taking objects of
Date class
//
displaying the dates on the
screen
date1.display();
date2.display();
date3.display();
}
The
output of the program is:
The
date is 1-1-1900
The
date is 1-1-2000
The
date is 10-12-2002
Summary
A class
is a user defined data type. It
has data members and member
functions. Normally
member functions
are called methods. Data
members are generally kept as private.
The
member functions,
used to manipulate the data
members, are kept public so
that these are
visible
from outside the class.
The public part of the
class is known as the
interface of the
class. It
may contain data members and
functions but normally we put functions
as
public.
The member functions can manipulate the
data members (public and
private) of
the
class. Non-member functions can
not see or access the
private part of the class.
We
try to
separate the implementation of
the class from its
interface.
Tips
·
Explicitly
write keyword private in the
class definition
·
Separate
the interface and
implementation
·
The
default constructor has no
arguments
·
Constructor
has the same name as of
class
·
The
data members of the class
are initialized at
runtime
·
Initializing
the data members in the
definition of the class is a syntax
error
Page
335
Table of Contents:
|
|||||