|
|
My Training Period: xx hours
The source code for this tutorial is available in C++ Polymorphism source code.
C++ abilities that should be acquired:
Able to understand and use:
▪ Polymorphism concept.▪ Virtual function.▪ Late and early binding.
17.1 Introduction
17.2 A Simple Program With Inheritance
|
1. // program poly1.cpp
2. #include <iostream>
3. using namespace std;
4.
5. // a base class declaration
6. // and the implementation part
7. class vehicle
8. {
9. int wheels;
10. float weight;
11. public:
12. void message(void) // first message()
13. {cout<<"Vehicle message, from vehicle, the base class\n";}
14. };
15.
16. // a derived class declaration and implementation part
17. class car : public vehicle
18. {
19. int passenger_load;
20. public:
21. void message(void) // second message()
22. {cout<<"Car message, from car, the vehicle derived class\n";}
23. };
24.
25. class truck : public vehicle
26. {
27. int passenger_load;
28. float payload;
29. public:
30. int passengers(void) {return passenger_load;}
31. };
32.
33. class boat : public vehicle
34. {
35. int passenger_load;
36. public:
37. int passengers(void) {return passenger_load;}
38. void message(void) // third message()
39. {cout<<"Boat message, from boat, the vehicle derived class\n";}
40. };
41.
42. // the main program
43. int main()
44. {
45. vehicle unicycle;
46. car sedan_car;
47. truck trailer;
48. boat sailboat;
49.
50. unicycle.message();
51. sedan_car.message();
52. trailer.message();
53. sailboat.message();
54.
55. // base and derived object assignment
56. unicycle = sedan_car;
57. unicycle.message();
58.
59. // system("pause”);
60. return 0;
61. }

This program is greatly simplified in order to effectively show you the use of a virtual function. You will notice that many of the methods from the last Module have been completely dropped from this example for simplicity, and a new method has been added to the base class, the method named message() in line 12 as shown below.
void message(void) // first message()
Throughout this Module we will be studying the operation of the method named message() in the base class and the derived classes. For that reason, there is another method named message() in the derived car and boat classes in lines 21 and 38 respectively as shown below:
void message(void) // second message()
...
void message(void) // third message()
You will also notice that there is no method named message() in the truck class. This has been done on purpose to illustrate the use of the virtual function/method. You will recall that the method named message() from the base class is available in the truck class because the method from the base class is inherited with the keyword public included in line 25 as shown below.
class truck : public vehicle
The main() program is as simple as the classes; one object of each of the classes is defined in lines 45 through 48 as shown below.
vehicle unicycle;
car sedan_car;
truck trailer;
boat sailboat;
And the method named message() is called once for each object. The output of this program indicates that the method for each is called except for the object named trailer, which has no method named message().
The method named message() from the base class is called and the data output to the screen indicates that this did happen.
Line 56 as shown below indicates how the derived object has been assigned to the base object,
unicycle = sedan_car;
And then calls the base object again in line 57 as shown below.
unicycle.message();
We are not concern with the data, so all the data is allowed to the default private type and none is inherited into the derived classes. Some of the data is left in the program example simply to make the classes look like classes.
The data could be removed since it is not used. Compile and run this program to see if your compiler gives a similar result.
Examine the next program example named poly2.cpp, you will notice that there is one small change in line 12. The keyword virtual has been added to the declaration of the method named message() in the base class.
1. // program poly2.cpp
2. #include <iostream>
3. using namespace std;
4.
5. // a base class declaration
6. // and the implementation part
7. class vehicle
8. {
9. int wheels;
10. float weight;
11. public:
12. virtual void message(void)
13. // first message(), with virtual keyword
14. {cout<<"Vehicle message, from vehicle, the base class\n";}
15. };
16.
17. // the derived class declaration and implementation part
18. class car : public vehicle
19. {
20. int passenger_load;
21. public:
22. void message(void) // second message()
23. {cout<<"Car message, from car, the vehicle derived class\n";}
24. };
25.
26. class truck : public vehicle
27. {
28. int passenger_load;
29. float payload;
30. public:
31. int passengers(void) {return passenger_load;}
32. };
33.
34. class boat : public vehicle
35. {
36. int passenger_load;
37. public:
38. int passengers(void) {return passenger_load;}
39. void message(void) // third message()
40. {cout<<"Boat message, from boat, the vehicle derived class\n";}
41. };
42.
43. // the main program
44. int main()
45. {
46. vehicle unicycle;
47. car sedan_car;
48. truck trailer;
49. boat sailboat;
50.
51. cout<<"Adding virtual keyword at the base class method\n";
52. cout<<"-----------------------------------------------\n";
53. unicycle.message();
54. sedan_car.message();
55. trailer.message();
56. sailboat.message();
57.
58. // unicycle = sedan_car;
59. // sedan_car.message();
60.
61. // system("pause");
62. return 0;
63. }

// unicycle = sedan_car; // sedan_car.message();
|
Examine the program example named poly3.cpp and you will find a repeat of the first program but with a different main program.
1. // program poly3.cpp
2. #include <iostream>
3. using namespace std;
4.
5. // a base class declaration
6. // and the implementation part
7. class vehicle
8. {
9. int wheels;
10. float weight;
11. public:
12. void message(void)
13. // first message()
14. {cout<<"Vehicle message, from vehicle, the base class\n";}
15. };
16.
17. // a derived class declaration and implementation part
18. class car : public vehicle
19. {
20. int passenger_load;
21. public:
22. void message(void) // second message()
23. {cout<<"Car message, from car, the vehicle derived class\n";}
24. };
25.
26. class truck : public vehicle
27. {
28. int passenger_load;
29. float payload;
30. public:
31. int passengers(void) {return passenger_load;}
32. };
33.
34. class boat : public vehicle
35. {
36. int passenger_load;
37. public:
38. int passengers(void) {return passenger_load;}
39. void message(void) // third message()
40. {cout<<"Boat message, from boat, the vehicle derived class\n";}
41. };
42.
43. // the main program
44. int main()
45. {
46. vehicle *unicycle;
47. car *sedan_car;
48. truck *trailer;
49. boat *sailboat;
50.
51. cout<<"Omitting the virtual keyword. Using\n";
52. cout<<"pointer variables, and new keyword\n";
53. cout<<"-----------------------------------\n";
54.
55. unicycle = new vehicle;
56. unicycle->message();
57. sedan_car = new car;
58. sedan_car->message();
59. trailer = new truck;
60. trailer->message();
61. sailboat = new boat;
62. sailboat->message();
63.
64. unicycle = sedan_car;
65. unicycle->message();
66.
67.
68. // system("pause");
69. return 0;
70. }

In this program the keyword virtual has been removed from the method declaration in the base class in line 12, and the main() program defines pointers to the objects rather than defining the objects themselves in lines 46 through 49 as shown below:
vehicle *unicycle;
car *sedan_car;
truck *trailer;
boat *sailboat;
Since we only defined pointers to the objects, we find it necessary to allocate the objects before using them by using the new operator in lines 55, 57, 59 and 61 as shown below:
unicycle = new vehicle;
...
sedan_car = new car;
...
trailer = new truck;
...
sailboat = new boat;
Upon running the program, we find that even though we are using pointers to the objects, we have done nothing different than what we did in the first program.
The program operates in exactly the same manner as the first program example. This should not be surprising because a pointer to a method can be used to operate on an object in the same manner as an object can be directly manipulated.
Be sure to compile and run this program before continuing on to the next program example. In this program you will notice that we failed to check the allocation to see that it did allocate the objects properly or not, and we also failed to de-allocate the objects prior to terminating the program.
In such a simple program, it doesn't matter because the heap will be cleaned up automatically when we return to the operating system.
In real program development you have to implement this allocation checking and the de-allocation. As shown in the previous Module, if we do not de-allocate, there will be garbage left.
The program example named poly4.cpp is identical to the last program except for the addition of the keyword virtual to line 12 once again.
1. // program poly4.cpp
2. #include <iostream>
3. using namespace std;
4.
5. // a base class declaration
6. // and the implementation part
7. class vehicle
8. {
9. int wheels;
10. float weight;
11. public:
12. virtual void message(void)
13. // first message(), with virtual keyword
14. {cout<<"Vehicle message, from vehicle, the base class\n";}
15. };
16.
17. // a derived class declaration and implementation part
18. class car : public vehicle
19. {
20. int passenger_load;
21. public:
22. &n