| My Training Period: xx hours
The source code for this tutorial is available in C++ Polymorphism source code.
The C++ programming skills that should be acquired:
Able to understand and use:
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 namedmessage() in line 12 as shown below.
void message(void) // first message()
Throughout this Module we will be studying the operation of the method namedmessage() in the base class and the derived classes. For that reason, there is another method namedmessage() in the derivedcar 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 keywordpublic included in line 25 as shown below.
class truck : public vehicle
Themain() 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 namedmessage() 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 defaultprivate 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 namedmessage() 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 themain() 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. 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<<"Re add 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. // system("pause");
68. return 0;
69. }
By including the keyword virtual, it is still identical to the last program. Once again we are simply using pointers to each of the objects, and in every case the pointer is of the same type as the object to which it points. You will begin to see some changes in the next program example.
Please compile and run this program. The four previous programs were meant just to show to you in what virtual functions do not do. The next two will show you what virtual functions do.
Examine the program example named poly5.cpp where we almost use a virtual function. We are almost ready to use a virtual method.
1. // program poly5.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.
47. cout<<"Omitting the virtual keyword. Using\n";
48. cout<<"pointer variables, new and\n";
49. cout<<"delete keyword\n";
50. cout<<"-----------------------------------\n";
51.
52. vehicle *unicycle;
53. unicycle = new vehicle;
54. unicycle->message();
55. delete unicycle;
56.
57. unicycle = new car;
58. unicycle->message();
59. delete unicycle;
60.
61. unicycle = new truck;
62. unicycle->message();
63. delete unicycle;
64.
65. unicycle = new boat;
66. unicycle->message();
67. delete unicycle;
68.
69. // unicycle = sedan_car;
70. // unicycle->message();
71.
72. // system("pause");
73. return 0;
74. }
The keywordvirtual omitted again in line 12 and with a totally different main() program. In this program, we only define a single pointer to a class and the pointer is pointing to the base class of the class hierarchy. We will use the single pointer to refer to each of the four classes and observe what the output of the method named message() is.
If we referred to a vehicle (in the real world, not necessarily in this program), we could be referring to a car, a truck, a motorcycle, or any other kinds of transportation, because we are referring to a very general form of an object.
If however, we were to refer to a car, we are excludingtrucks, motorcycles, and all other kinds of transportation, because we are referring to acar specifically. The more general term ofvehicle can therefore refer to a many kinds of vehicles, but the more specific term of car can only refer to a single kind of vehicle, namely acar.
We can apply the same thought process in C++ and say that if we have a pointer to a vehicle, we can use that pointer to refer to any of the more specific objects whereas if we have a pointer to a car, we cannot use that pointer to reference any of the other classes including thevehicle class because the pointer to thecar class is too specific and restricted to be used on any other classes.
tenouk C++ polymorphism programming
The source code for this tutorial is available inC++ Polymorphism source code.
Check the best selling C/C++, Object Oriented and pattern analysis books at Amazon.com.
Find a lot of information about C++ history and evolution at Bjarne Stroustrup site (http://www.stroustrup.com/).