OUR FIRST DERIVED CLASS
Examine the file named CAR.H for our first example of the use of a derived class or child class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #ifndef CAR_H #define CAR_H #include "vehicle.h" class car : public vehicle { int passenger_load; public: void initialize(int in_wheels, float in_weight, int people = 4); int passengers(void); }; #endif // Result of execution // // (this file cannot be executed) |
The vehicle class is inherited due to the “: public vehicle” added to line 4. This derived class named car is composed of all of 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.
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // car.cpp #include "car.h" void car::initialize(int in_wheels, float in_weight, int people) { passenger_load = people; wheels = in_wheels; weight = in_weight; } int car::passengers(void) { return passenger_load; } // Result of execution // // (this file cannot be executed) |
The 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.
ANOTHER DERIVED CLASS
Examine the file named TRUCK.H for an example of another class that uses the vehicle class and adds to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //truch.h #ifndef TRUCK_H #define TRUCK_H #include "vehicle.h" class truck : public vehicle { int passenger_load; float payload; public: void init_truck(int how_many = 2, float max_load = 24000.0); float efficiency(void); int passengers(void); }; #endif |
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.
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 nothing unusual included in it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // truck.cpp #include "truck.h" void truck::init_truck(int how_many, float max_load) { passenger_load = how_many; payload = max_load; } float truck::efficiency(void) { return payload / (payload + weight); } int truck::passengers(void) { return passenger_load; } // Result of execution // // (this file cannot be executed) |
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 classes we have been discussing in this chapter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | // allvehic.cpp #include <iostream.h> #include "vehicle.h" #include "car.h" #include "truck.h" main() { vehicle unicycle; unicycle.initialize(1, 12.5); cout << "The unicycle has " << unicycle.get_wheels() << " wheel.n"; cout << "The unicycle's wheel loading is " << unicycle.wheel_loading() << " pounds on the single tire.n"; cout << "The unicycle weighs " << unicycle.get_weight() << " pounds.nn"; car sedan; sedan.initialize(4, 3500.0, 5); cout << "The sedan carries " << sedan.passengers() << " passengers.n"; cout << "The sedan weighs " << sedan.get_weight() << " pounds.n"; cout << "The sedan's wheel loading is " << sedan.wheel_loading() << " pounds per tire.nn"; truck semi; semi.initialize(18, 12500.0); semi.init_truck(1, 33675.0); cout << "The semi weighs " << semi.get_weight() << " pounds.n"; cout << "The semi's efficiency is " << 100.0 * semi.efficiency() << " percent.n"; } // Result of execution // // The unicycle has 1 wheel. // The unicycle's wheel loading is 12.5 pounds on the single tire. // The unicycle weighs 12.5 pounds. // // The sedan carries 5 passengers. // The sedan weighs 3500 pounds. // The sedan's wheel loading is 875 pounds per tire. // // The semi weighs 12500 pounds. // The semi's efficiency is 72.929072 percent. |
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
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.