home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware 1 2 the Maxx
/
sw_1.zip
/
sw_1
/
PROGRAM
/
CPTUTT22.ZIP
/
CHAP07.TXT
< prev
next >
Wrap
Text File
|
1992-01-20
|
22KB
|
472 lines
Chapter 7
INHERITANCE
One reason to use inheritance is that it allows you to reuse code
from a previous project but gives you the flexibility to slightly
modify it if the old code doesn't do exactly what you need for the
new project. It doesn't make sense to start every new project from
scratch since some code will certainly be repeated in several
programs and you should strive to build on what you did previously.
Moreover, it is easy to make an error if we try to modify the
original class, but we are less likely to make an error if we leave
the original alone and only add to it. Another reason for using
inheritance is if the project requires the use of several classes
which are very similar but slightly different.
In this chapter we will concentrate on the mechanism of inheritance
and how to build it into a program. A better illustration of why
you would use inheritance will be given in later chapters where we
will discuss some practical applications of object oriented
programming.
The principle of inheritance is available with several modern
programming languages and is handled slightly differently with
each. C++ allows you to inherit all or part of the members and
methods of a class, modify some, and add new ones not available in
the parent class. You have complete flexibility, and as usual,
the method used with C++ has been selected to result in the most
efficient code execution.
A SIMPLE CLASS TO START WITH
_________________________________________________________________
Examine the file named VEHICLE.H for a simple =================
class which we will use to begin our study of VEHICLE.H
inheritance in this chapter. There is nothing =================
unusual about this class header, it has been
kept very simple. It consists of four simple
methods which can be used to manipulate data pertaining to our
vehicle. What each method does is not especially important at this
time. We will eventually refer to this as a base class or parent
class, but for the time being, we will simply use it like any other
class to show that it is indeed identical to the classes already
studied. Note that we will explain the added keyword protected
shortly.
Ignore lines 4, 5, and 17 until the end of this chapter where they
will be explained in detail. This file cannot be compiled or
executed because it is only a header file.
Page 7-1
Chapter 7 - Inheritance
THE IMPLEMENTATION FOR VEHICLE
_________________________________________________________________
Examine the file named VEHICLE.CPP and you will ===============
find that it is the implementation of the VEHICLE.CPP
vehicle class. The initialize() method assigns ===============
the values input as parameters to the wheels and
weight variables. We have methods to return the
number of wheels and the weight, and finally, we have one that does
a trivial calculation to return the loading on each wheel. We will
have a few examples of methods that do some significant processing
later, but at this point, we are more interested in learning how
to set up the interface to the classes, so the implementations will
be kept trivial.
As stated above, this is a very simple class which will be used in
the next program. Later in this tutorial we will use it as a base
class. You should compile this class at this time in preparation
for the next example program, but you cannot execute it because
there is no entry point.
USING THE VEHICLE CLASS
_________________________________________________________________
The file named TRANSPRT.CPP uses the vehicle ================
class in exactly the same manner as we TRANSPRT.CPP
illustrated in the last chapter. This should be ================
an indication to you that the vehicle class is
truly nothing more than a normal class as
defined in C++. We will make it a little special, however, by
using it unmodified as a base class in the next few example files
to illustrate inheritance. Inheritance uses an existing class and
adds functionality to it to accomplish another, possibly more
complex job.
You should have no problem understanding the operation of this
program. It declares four objects of the vehicle class,
initializes them, and prints out a few of the data points to
illustrate that the vehicle class can be used as a simple class
because it is a simple class. We are referring to it as a simple
class as opposed to calling it a base class or derived class as we
will do shortly.
If you thoroughly understand this program, you should compile and
execute it, remembering to link the vehicle object file with this
object file.
OUR FIRST DERIVED CLASS
_________________________________________________________________
Examine the file named CAR.H for our first example of the use of
a derived class or child class. The vehicle class is inherited due
Page 7-2
Chapter 7 - Inheritance
to the ": public vehicle" added to line 4. This ==============
derived class named car is composed of all of CAR.H
the information included in the base class ==============
vehicle, and all of its own additional
information. Even though we did nothing to the
class named vehicle, we made it into a base class because of the
way we are using it here. To go a step further, even though it
will be used as a base class in an example program later in this
chapter, there is no reason it cannot continue to be used as a
simple class in the previous example program. In fact, it can be
used as a single class and a base class in the same program. The
question of whether it is a simple class or a base class is
answered by the way it is used.
A discussion of terminology is needed here. When discussing object
oriented programming in general, a class that inherits another is
often called a derived class or a child class, but the most proper
term as defined for C++ is a derived class. Since these terms are
very descriptive, and most writers tend to use the terms
interchangeably, we will also use these terms in this tutorial.
Likewise the proper C++ terminology for the inherited class is to
call it a base class, but parent class and super class are
sometimes used.
A base class is a rather general class which can cover a wide range
of objects, whereas a derived class is somewhat more restricted but
at the same time more useful. For example if we had a base class
named programming language and a derived class named C++, then we
could use the base class to define Pascal, Ada, C++, or any other
programming language, but it would not tell us about the use of
classes in C++ because it can only give a general view of each
language. On the other hand, the derived class named C++ could
define the use of classes, but it could not be used to describe the
other languages because it is too narrow. A base class tends to
be more general, and a derived class is more specific.
In this case, the vehicle base class can be used to declare objects
that represent trucks, cars, bicycles, or any number of other
vehicles you can think up. The class named car however can only
be used to declare an object that is of type car because we have
limited the kinds of data that can be intelligently used with it.
The car class is therefore more restrictive and specific than the
vehicle class. The vehicle class is more general than the car
class.
If we wished to get even more specific, we could define a derived
class using car as the base class and name it sports_car and
include such information as red_line_limit for the tachometer which
would be silly for the family station wagon. The car class would
therefore be used as a derived class and a base class at the same
time, so it should be clear that these names refer to how a class
is used.
Page 7-3
Chapter 7 - Inheritance
HOW DO WE DECLARE A DERIVED CLASS?
_________________________________________________________________
Enough generalities about classes, let's get down to the specifics.
A derived class is defined by including the header file for the
base class as is done in line 2, then the name of the base class
is given following the name of the derived class separated by a
colon as is illustrated in line 4. Ignore the keyword public
immediately following the colon in this line. It is optional and
we will study it in detail in the next chapter. All objects
declared as being of class car therefore are composed of the two
variables from the class vehicle because they inherit those
variables, and the single variable declared in the class car named
passenger_load.
An object of this class will have three of the four methods of
vehicle and the two new ones declared here. The method named
initialize() which is part of the vehicle class will not be
available here because it is hidden by the local version of
initialize() which is a part of the car class. The local method
will be used if the name is repeated allowing you to customize your
new class. Figure 7-1 is a graphical representation of an object
of this class.
Note once again that the implementation for the base class only
needs to be supplied in its compiled form. The source code for the
implementation can be hidden for economic reasons to aid software
developers. Hiding the source code also allows the practice of
information hiding. The header for the base class must be
available as a text file since the class definitions are required
in order to use the class.
THE CAR CLASS IMPLEMENTATION
_________________________________________________________________
Examine the file named CAR.CPP which is the ===============
implementation file for the car class. The CAR.CPP
first thing you should notice is that this file ===============
has no indication of the fact that it is a
derived class of any other file, that can only
be determined by inspecting the header file for the class. Since
we can't tell if it is a derived class or not, it is written in
exactly the same way as any other class implementation file.
The implementations for the two new methods are written in exactly
the same way as methods are written for any other class. If you
think you understand this file, you should compile it for later
use.
Page 7-4
Chapter 7 - Inheritance
ANOTHER DERIVED CLASS
_________________________________________________________________
Examine the file named TRUCK.H for an example of ===============
another class that uses the vehicle class and TRUCK.H
adds to it. Of course, it adds different things ===============
to it because it will specialize in those things
that pertain to trucks. In fact it adds two
more variables and three methods. Once again, ignore the keyword
public following the colon in line 7 for a few minutes and we will
cover it in detail in the next chapter of this tutorial. See
figure 7-2.
A very important point that must be made is that the car class and
the truck class have absolutely nothing to do with each other, they
only happen to be derived classes of the same base class or parent
class as it is sometimes called.
Note that both the car and the truck classes have methods named
passengers() but this causes no problems and is perfectly
acceptable. If classes are related in some way, and they certainly
are if they are both derived classes of a common base class, you
would expect them to be doing somewhat similar things. In this
situation there is a good possibility that a method name would be
repeated in both child classes.
THE TRUCK IMPLEMENTATION
_________________________________________________________________
Examine the file named TRUCK.CPP for the =================
implementation of the truck class. It has TRUCK.CPP
nothing unusual included in it. =================
You should have no problem understanding this
implementation. Your assignment at this point is to compile it in
preparation for our example program that uses all three of the
classes defined in this chapter.
USING ALL THREE CLASSES
_________________________________________________________________
Examine the example program named ALLVEHIC.CPP ================
for an example that uses all three of the ALLVEHIC.CPP
classes we have been discussing in this chapter. ================
It uses the parent class vehicle to declare
objects and also uses the two child classes to
declare objects. This was done to illustrate that all three
classes can be used in a single program.
All three of the header files for the classes are included in lines
3 through 5 so the program can use the components of the classes.
Notice that the implementations of the three classes are not in
Page 7-5
Chapter 7 - Inheritance
view here and do not need to be in view. This allows the code to
be used without access to the source code for the actual
implementation of the class. However, it should be clear that the
header file definition must be available.
In this example program, only one object of each class is declared
and used but as many as desired could be declared and used in order
to accomplish the programming task at hand. You will notice how
clean and uncluttered the source code is for this program since the
classes were developed, debugged, and stored away previously, and
the interfaces were kept very simple. There is nothing new here
so you should have no trouble understanding the operation of this
program.
Compiling and executing this program will take a bit of effort but
the process is not complicated. The three classes and the main
program can be compiled in any order desired. All four must be
compiled prior to linking the four resulting object (or binary)
files together. Finally, you can execute the complete program.
Be sure you do the required steps to compile and execute this
program because the effective use of C++ will require you to
compile many separate files and link them together. This is
because of the nature of the C++ language, but it should not be a
burden if a good "make" capability exists with your compiler. If
you are using the Borland implementation of C++, the "project"
capability will make this a snap.
WHY THE #ifndef VEHICLE_H ?
_________________________________________________________________
We promised to return to the strange looking preprocessor directive
in lines 4, 5 and 17 in the VEHICLE.H file, and this is the time
for it. When we define the derived class car, we are required to
supply it with the full definition of the interface to the vehicle
class since car is a derived class of vehicle and must know all
about its parent. We do that by including the vehicle class into
the car class, and the car class can be compiled. The vehicle
class must also be included in the header file of the truck class
for the same reason.
When we get to the main program, we must inform it of the details
of all three classes, so all three header files must be included
as is done in lines 3 through 5 of ALLVEHIC.CPP, but this leads to
a problem. When the preprocessor gets to the car class, it
includes the vehicle class because it is listed in the car class
header file, but since the vehicle class was already included in
line 3 of ALLVEHIC.CPP, it is included twice and we attempt to
redefine the class vehicle. Of course it is the same definition,
but the system doesn't care, it simply doesn't allow redefinition
of a class. We allow the double inclusion of the file and at the
same time prevent the double inclusion of the class by building a
bridge around it using the word VEHICLE_H. If the word is already
defined, the definition is skipped, but if the word is not defined,
Page 7-6
Chapter 7 - Inheritance
the definition is included and the word is defined at that time.
The end result is the actual inclusion of the class only once, even
though the file is included more than once. You should have no
trouble understanding the logic of the includes if you spend a
little time studying this program sequence.
Even though ANSI-C allows multiple definitions of entities,
provided the definitions are identical, C++ does not permit this.
The primary reason is because the compiler would have great
difficulty in knowing if it has already made a constructor call for
the redefined entity, if there is one. A multiple constructor call
for a single object could cause great havoc, so C++ was defined to
prevent any multiple constructor calls by making it illegal to
redefine any entity. This is not a problem in any practical
program.
The name VEHICLE_H was chosen as the word because it is the name
of the file, with the period replaced by the underline. If the
name of the file is used systematically in all of your class
definitions, you cannot have a name clash because the filename of
every class must be unique. It would be good for you to get into
the practice of building the optional skip around all of your
classes. All class definition files in the remainder of this
tutorial will include this skip around to prevent multiple
inclusions and to be an example for you. You should get into the
practice of adding the skip around to all of your class headers no
matter how trivial they may seem to be.
OUR FIRST PRACTICAL INHERITANCE
_________________________________________________________________
Continuing where we started in chapter 5, we ===============
will inherit the date class into the file named NEWDATE.H
NEWDATE.H and add a member variable and a new ===============
method to the class. Actually, this is not a
good way to add the day_of_year to the date
class since it is available in the structure returned from the
system call in the date class. However, we are more interested in
illustrating inheritance in a practical example than we are in
developing a perfect class, so we will live with this inefficiency.
You will note that we add one variable and one method to create our
new class.
The program named NEWDATE.CPP contains the ===============
implementation for the added method and should NEWDATE.CPP
be simple for the student to understand. This ===============
class implementation uses the array days[] from
the date class implementation since it was
defined as a global variable there. The method named
get_time_of_day() involves very simple logic but still adjusts for
leap years.
Page 7-7
Chapter 7 - Inheritance
Finally, the example program named TRYNDATE.CPP ================
will use the new class in a very simple way to TRYNDATE.CPP
illustrate that the derived class is as easy to ================
use as the base class and in fact the main
program has no way of knowing that it is using
a derived class.
You should compile and link this program to gain the experience of
doing so. Remember that it will be necessary to link in the object
code for the original date class as well as the object code from
the newdate class and the main program.
PROGRAMMING EXERCISES
_________________________________________________________________
1. Add another object of the vehicle class to ALLVEHIC.CPP named
bicycle, and do some of the same operations as were done to
the unicycle. You will only need to recompile the main
program and link all four files together to get an executable
file, the three classes will not require recompilation.
2. Add the optional skip around the header files of the classes
named car and truck. Then recompile all four files and relink
them to get an executable file.
3. Add a new method to the truck class to return the total weight
of the truck plus its payload and add code to ALLVEHIC.CPP to
read the value out and display it on the monitor. This will
require an addition to TRUCK.H, another addition to TRUCK.CPP,
and of course the changes to the main program named
ALLVEHIC.CPP. The answer is given as three files named
CH07_3A.H (TRUCK.H), CH07_3B.CPP (TRUCK.CPP) and the changed
main program is found in CH07_3C.CPP in the answer directory
on the distribution disk for this tutorial.
4. Add a variable named sex of type char to the name class you
developed in chapter 5 as well as methods to set and retrieve
the value of this variable. The only legal inputs are 'M' or
'F'. These additions should be done by inheriting the name
class into the new class.
Page 7-8