The source code for this session is available in C++ Multi Inheritance source code.
| 16.4 Duplicated Variable Names
1. // program mulinher3.cpp 2. #include <iostream> 3. using namespace std; 4. 5. // class declaration and implementation part 6. // class #1 7. class moving_van 8. { 9. protected: 10. float payload; 11. float weight; // note this variable 12. float mpg; 13. public: 14. void initialize(float pl, float gw, float input_mpg) 15. { 16. payload = pl; 17. weight = gw; 18. mpg = input_mpg; 19. }; 20. 21. float efficiency(void) 22. { return(payload / (payload + weight)); }; 23. 24. float cost_per_ton(float fuel_cost) 25. { return (fuel_cost / (payload / 2000.0)); }; 26. }; 27. 28. // class #2 29. class driver 30. { 31. protected: 32. float hourly_pay; 33. float weight; // another weight variable 34. // variable with same name as in class number one 35. public: 36. void initialize(float pay, float input_weight) 37. // same method name but different number of parameter 38. { 39. hourly_pay = pay; 40. weight = input_weight; 41. }; 42. float cost_per_mile(void) {return (hourly_pay / 55.0); } ; 43. float drivers_weight(void) {return (weight); }; 44. }; 45. 46. // derived class with multi inheritance 47. // declaration and implementation 48. class driven_truck : public moving_van, public driver 49. { 50. public: 51. void initialize_all(float pl, float gw, float input_mpg, float pay) 52. // another same method name but different number of parameter 53. { 54. payload = pl; 55. moving_van::weight = gw; 56. mpg = input_mpg; 57. hourly_pay = pay; 58. }; 59. 60. float cost_per_full_day(float cost_of_gas) 61. { return ((8.0 * hourly_pay) + (8.0 * cost_of_gas * 55.0) / mpg); }; 62. 63. float total_weight(void) 64. // see, how to call different variables with same name 65. { 66. cout<<"\nCalling appropriate member variable\n"; 67. cout<<"---->(moving_van::weight)+(driver::weight)\n"; 68. cout<<"------------------------------------------\n"; 69. return ((moving_van::weight) + (driver::weight)); 70. }; 71. }; 72. 73. // the main program 74. int main() 75. { 76. driven_truck john_merc; 77. 78. john_merc.initialize_all(20000.0, 12000.0, 5.2, 12.50); 79. // accessing the derived class method 80. john_merc.driver::initialize(15.50, 250.0); 81. // accessing the base class number two 82. 83. cout<<"The efficiency of the Merc is "<<john_merc.efficiency()<<" %\n"; 84. cout<<"The cost per mile for John to drive is 85. $"<<john_merc.cost_per_mile()<<"\n"; 86. cout<<"The cost per day for John to drive Merc is 87. $"<<john_merc.cost_per_full_day(1.129)<<"\n"; 88. cout<<"The total weight is "<<john_merc.total_weight()<<" ton\n"; 89. 90. // system("pause"); 91. return 0; 92. }
92 Lines: Output:
|
According to the rules of inheritance, an object of the driven_truck class will have two variables with the same name, weight. This would be a problem if it weren’t for the fact that C++ has defined a method of accessing each one in a well defined way. We have to use qualification to access each variable.
Line 69 as shown below, illustrates the use of the variables. It may be obvious, but it should be explicitly stated, the derived class itself can have a variable of the same name as those inherited from the base classes. In order to access it, no qualification would be required, but qualification with the derived class name is permitted.
return ((moving_van::weight) + (driver::weight));
It should be apparent to you that once you understand single inheritance, multiple inheritances is nothing more than an extension of the same rules. Of course, if you inherit two methods or variables of the same name, you must use qualification to allow the compiler to select the correct one.
Constructors are called for both classes before the derived class constructor is executed. The constructors for the base classes are called in the order they are declared in the class header.
Compile and run this program.
Many times, when developing a program, you wish to perform some operation on more than one data type with same program routine. For example you may wish to sort a list of integers, another list of floating point numbers, and a list of alphabetic strings but the sorting routine should be same.
It seems silly to write a separate sort function for each of the three types when all three are sorted in the same logical way.
With parameterized types, you will be able to write a single sort routine that is capable of sorting all the three different types of data.
This is already available in other programming language such as ADA language as the generic package or procedure.
There is already a library of these components available, as a part of the ANSI/ISO/IEC C++ standard and most of the C++ compilers available in the market. It is called theStandard Template Library, usually referred to as STL.
It will be very beneficial for you to study this and learn how to use it in your programs. Assume this section as an introduction of the generic programming.
The following program example named template1.cpp is our first example of the template and their usage. This simple program just to illustrate the use of the parameterized type.
1. // using function template
2. #include <iostream>
3. using namespace std;
4.
5. // template declaration
6. template
7. <class ANY_TYPE> ANY_TYPE maximum(ANY_TYPE a, ANY_TYPE b)
8. {
9. return (a > b) ? a : b;
10. }
11.
12. // the main program
13. int main(void)
14. {
15. int x = 10, y = -9;
16. float real = 3.1415;
17. char ch = 'C';
18.
19. cout<<"maximum("<<x<<", "<<y<<") = "<<maximum(x, y)<<"\n";
20. cout<<"maximum(-47, "<<y<<") = "<<maximum(-47,y)<<"\n";
21. cout<<"maximum("<<real<<", "<<float(y)<<") =
22. "<<maximum(real,float(y))<<"\n";
23. cout<<"maximum("<<real<<", "<<float(x)<<") =
24. "<<maximum(real,float(x))<<"\n";
25. cout<<"maximum("<<ch<<", "<<'A'<<") = "<<maximum(ch, 'A')<<"\n";
26.
27. // system("pause");
28.
29. return 0;
30. }
The template is given in lines 6 through 10 as shown below with the first line indicating that it is a template with a single type to be replaced, the ANY_TYPE type.
// template declaration
template <class ANY_TYPE> ANY_TYPE maximum(ANY_TYPE a, ANY_TYPE b)
{
return (a > b) ? a : b;
}
16.7 Template - A Class template
|
1. // a class template
2. #include <iostream>
3. using namespace std;
4.
5. const int MAXSIZE = 128;
6.
7. // a class template
8. template <class ANY_TYPE> class stack
9. {
10. ANY_TYPE array[MAXSIZE];
11. int stack_pointer;
12. public:
13. stack(void) { stack_pointer = 0; };
14. void push(ANY_TYPE input_data){ array[stack_pointer++] = input_data; };
15. ANY_TYPE pop(void) { return array[--stack_pointer]; };
16. int empty(void) { return (stack_pointer == 0); };
17. };
18.
19. char name[ ] = "Testing, this is an array, name[ ]";
20.
21. // the main program
22. int main(void)
23. {
24. int x = 30, y = -10;
25. float real = 4.2425;
26.
27. stack<int> int_stack;
28. stack<float> float_stack;
29. stack<char *> string_stack;
30.
31. // storing data
32. int_stack.push(x);
33. int_stack.push(y);
34. int_stack.push(67);
35.
36. float_stack.push(real);
37. float_stack.push(-20.473);
38. float_stack.push(107.03);
39.
40. string_stack.push("This is the first line of string");
41. string_stack.push("This is the second line of string");
42. string_stack.push("This is the third line of string");
43. string_stack.push(name);
44.
45. // displaying data
46. cout<<"---------------Displaying data--------------------\n";
47. cout<<"\nInteger stack\n";
48. cout<<"-------------\n";
49. cout<<"Access using int_stack.pop(), first time : "<<int_stack.pop()<<"\n";
50. cout<<"Access using int_stack.pop(), second time: "<<int_stack.pop()<<"\n";
51. cout<<"Access using int_stack.pop(), third time : "<<int_stack.pop()<<"\n";
52.
53. cout<<"\nFloat stack\n";
54. cout<<"-------------\n";
55. cout<<"Access using float_stack.pop(), first time :
56. "<<float_stack.pop()<<"\n";
57. cout<<"Access using float_stack.pop(), second time:
58. "<<float_stack.pop()<<"\n";
59. cout<<"Access using float_stack.pop(), third time :
60. "<<float_stack.pop()<<"\n";
61.
62. cout<<"\nString stack\n";
63. cout<<"-------------\n";
64. do
65. {
66. cout<<"Access using string_stack.pop(): "<<string_stack.pop()<<"\n";
67. } while (!string_stack.empty());
68.
69.
70. // system("pause");
71. return 0;
72. }
In themain() program we create an object namedint_stack in line 27 which will be a stack designed to store integers, and another object namedfloat_stack in line 28 which is designed to store float type values as shown below:
stack<int> int_stack;
stack<float> float_stack;
In both cases, we enclose the type we desire this object to work with in "<>" brackets and the system creates the object by first replacing all instances of ANY_TYPE with the desired type, then creating the object of that type.
You will notice that any type can be used that has an assignment capability since lines 13 and 14 use the assignment operator on the parameterized type. The assignment operator is used in line 14 because it returns an object of that type which must be assigned to something in the calling program.
Even though the strings are all of different lengths, we can even use the stack to store the strings if we only store a pointer to the strings and not the entire string. This is illustrated in the object named string_stack defined in line 29 and used later in the program.
Compile and run this program and appreciate it :o).
You will learn a lot more things about templates, theStandard Template Library.
tenouk fundamental of C++ multi-inheritance programming
The source code is available in C++ Multi Inheritance source code.
Check the best selling C / C++ and object oriented books at Amazon.com.
The Visual C++ .NET programming tutorials.
Typecasting that discussed in C/C++ Typecasting tutorial extensively deals with Inheritance and Multi inheritance.