class Base
class Derived1
class Derived2
class Derived3
class Derived4
1: /** @file name_hiding2.cpp
2: Based on an example from Eckel, Thinking in C++, 2nd edition.
3: */
5: #include <iostream>
6: #include <string>
7: using namespace std;
9: class Base
10: {
11: public:
12: virtual int f() const
13: {
14: cout << "\nExecuting Base::f() with int return type.";
15: cout << "\nPress Enter to continue ... "; cin.ignore(80, '\n');
16: return 1;
17: }
19: virtual void f(string s) const
20: {
21: cout << "\nExecuting Base::f(string) with void return type.";
22: cout << "\nPress Enter to continue ... "; cin.ignore(80, '\n');
23: }
25: virtual void g() const
26: {
27: cout << "\nExecuting Base::g() with void return type.";
28: cout << "\nPress Enter to continue ... "; cin.ignore(80, '\n');
29: }
30: };
33: class Derived1 : public Base
34: {
35: public:
36: void g() const
37: {
38: cout << "\nExecuting Derived1::g() with void return type.";
39: cout << "\nPress Enter to continue ... "; cin.ignore(80, '\n');
40: }
41: };
44: class Derived2 : public Base
45: {
46: public:
47: //Overriding a virtual function:
48: int f() const
49: {
50: cout << "\nExecuting Derived2::f() with int return type.";
51: cout << "\nPress Enter to continue ... "; cin.ignore(80, '\n');
52: return 2;
53: }
54: };
57: class Derived3 : public Base
58: {
59: public:
60: //Cannot change return type:
61: //void f() const
62: //{
63: // cout << "\nExecuting Derived3::f() with void return type.";
64: // cout << "\nPress Enter to continue ... "; cin.ignore(80, '\n');
65: //}
66: };
69: class Derived4 : public Base
70: {
71: public:
72: //Change argument list:
73: int f(int) const
74: {
75: cout << "\nExecuting Derived4::f(int) with int return type.";
76: cout << "\nPress Enter to continue ... "; cin.ignore(80, '\n');
77: return 4;
78: }
79: };
82: int main()
83: {
84: cout << "\nThis program illustrates how virtual functions restrict "
85: "their overloading\nin derived classes, and shows how this "
86: "prevents the breaking of the\n\"polymorphic contract\" that "
87: "virtual functions provide.";
88: cout << "\nPress Enter to continue ... "; cin.ignore(80, '\n');
90: string s("hello");
91: int n;
93: Derived1 d1;
94: n = d1.f();
95: d1.f(s);
97: Derived2 d2;
98: n = d2.f();
99: //d2.f(s); //1string version hidden
100: //error C2660: 'Derived2::f' : function does not take 1 arguments
103: Derived4 d4;
104: n = d4.f(1);
105: //n = d4.f(); //2f() version hidden
106: //error C2660: 'Derived4::f' : function does not take 0 arguments
108: //d4.f(s); //3string version hidden
109: //error C2664: 'Derived4::f' :
110: //cannot convert parameter 1 from 'std::string' to 'int'
112: Base& br = d4; //Upcast
113: //br.f(1); //4Derived version unavailable
114: //error C2664: 'void Base::f(std::string) const' :
115: //cannot convert parameter 1 from 'int' to 'std::string'
117: br.f(); //Base version available
118: br.f(s); //Base version available
119: }
121: /*
122: Output
123: ------
125: This program illustrates how virtual functions restrict their overloading
126: in derived classes, and shows how this prevents the breaking of the
127: "polymorphic contract" that virtual functions provide.
128: Press Enter to continue ...
130: Executing Base::f() with int return type.
131: Press Enter to continue ...
133: Executing Base::f(string) with void return type.
134: Press Enter to continue ...
136: Executing Derived2::f() with int return type.
137: Press Enter to continue ...
139: Executing Derived4::f(int) with int return type.
140: Press Enter to continue ...
142: Executing Base::f() with int return type.
143: Press Enter to continue ...
145: Executing Base::f(string) with void return type.
146: Press Enter to continue ...
147: Press any key to continue . . .
148: */
150: /*
151: Notes:
152: In Derived3, the compiler will not let you change the return type of
153: the overriden function f(). It would be allowed if f() were not virtual.
154: This is an important restriction because the compiler must guarantee
155: that you can polymorphically call the function through the base class,
156: and if the base class is expecting an int to be returned from f() then
157: the derived class version of f() must keep that part of the contract or
158: else things will break.
160: As before, if you override one of the overloaded member functions in the
161: base class the other overloaded versions become hidden in the derived
162: class. In main(), the code that tests Derived4 shows that this happens
163: even if the new version of f() isn't actually overriding an existing
164: virtual function interface-both of the base-class versions of f() are
165: hidden by f(int). However, if you upcast d4 to Base, then only the
166: base-class versions are available (because that's what the base-class
167: contract promises) and the derived-class version is not available
168: (because it isn't specified in the base class).
169: */