In this lesson, you learned about the advanced features of Visual C++. You learned how to make one class out of another and how to change the way a function is called to depend on either the calling type or the object type.
In this lesson, you saw the following:
Project 11 Listing. An object-oriented pet care program.
1:// File name : PROJCT11.CPP 2:// Object oriented pet program to manage 3:// a simple list of different types of 4:// pets 5:// 6:#include <iostream.h> 7:#include <string.h> 8: 9://------------------------------------------------------------ 10:// Pet class 11:// 12:class Pet 13: { 14: public: 15: virtual ~Pet() // Destructor 16: { 17: delete [] name; 18: } 19: void Print() const; // Print all about pet 20: void Query(); // Get details 21: const char * GetName() const// Provide name string 22: { 23: if (name) 24: return name; 25: else 26: return ""; 27: } 28: protected: 29: virtual void PrintDetails() const = 0;// Print details 30: virtual void QueryDetails() = 0; // Ask for details 31: virtual const char * GetPetType() const = 0; 32: Pet() // protected - 33: // do not make Pets 34: { 35: name = 0; 36: } 37: private: 38: char * name; 39: }; 40:void Pet::Print() const 41: { 42: cout << GetPetType() << " : "; 43: if (name) 44: cout << name << " - "; 45: PrintDetails(); 46: cout << endl; 47: } 48: 49:void Pet::Query() 50: { 51: char tempName[81]; 52: cout << "What is your pet " << GetPetType() <<"'s name? "; 53: cin.getline(tempName,81); 54: if (name) 55: delete [] name; 56: name = new char[strlen(tempName) + 1]; 57: strcpy(name,tempName); 58: QueryDetails(); 59: } 60: 61://------------------------------------------------------------ 62:// Cat class - derived from Pet 63:// 64:class Cat : public Pet 65: { 66: public: 67: Cat(int Scratches = 1) 68: { 69: scratches = Scratches; 70: } 71: protected: 72: virtual void PrintDetails() const; 73: virtual void QueryDetails(); 74: const char * GetPetType() const 75: { 76: return "Cat"; 77: } 78: private: 79: int scratches; 80: }; 81: 82:void Cat::PrintDetails() const 83: { 84: cout << "Scratches: " << (scratches? "Yes":"No"); 85: } 86: 87:void Cat::QueryDetails() 88: { 89: char yn; 90: cout << "Does your cat " << GetName() << " scratch? "; 91: cin >> yn; 92: cin.ignore(80,'\n'); 93: if (yn == 'Y' || yn == 'y') 94: scratches = 1; 95: else 96: scratches = 0; 97: } 98: 99://------------------------------------------------------------ 100:// Dog class - derived from Pet 101:// 102: 103:class Dog : public Pet 104: { 105: public: 106: Dog(int Barks = 1) 107: { 108: barks = Barks; 109: } 110: protected: 111: virtual void PrintDetails() const; 112: virtual void QueryDetails(); 113: const char * GetPetType() const 114: { 115: return "Dog"; 116: } 117: private: 118: int barks; 119: }; 120: 121:void Dog::PrintDetails() const 122: { 123: cout << "Barks: " << (barks? "Yes":"No"); 124: } 125: 126:void Dog::QueryDetails() 127: { 128: char yn; 129: cout << "Does your dog " << GetName() << " bark? "; 130: cin >> yn; 131: cin.ignore(80,'\n'); 132: if (yn == 'Y' || yn == 'y') 133: barks = 1; 134: else 135: barks = 0; 136: } 137: 138://------------------------------------------------------------ 139:// Fish class - derived from Pet 140:// 141:class Fish : public Pet 142: { 143: public: 144: Fish(int ColdWater = 0) 145: { 146: coldWater = ColdWater; 147: } 148: protected: 149: virtual void PrintDetails() const; 150: virtual void QueryDetails(); 151: const char * GetPetType() const 152: { 153: return "Fish"; 154: } 155: private: 156: int coldWater; 157: }; 158:void Fish::PrintDetails() const 159: { 160: cout << (coldWater? "Cold water":"Tropical"); 161: } 162: 163:void Fish::QueryDetails() 164: { 165: char yn; 166: cout << "Is your fish " << GetName() << " tropical? "; 167: cin >> yn; 168: cin.ignore(80,'\n'); 169: if (yn == 'Y' || yn == 'y') 170: coldWater = 0; 171: else 172: coldWater = 1; 173: } 174: 175://------------------------------------------------------------ 176:// main procedure 177:// 178: 179:void main() 180: { 181: const int maxPets = 20; 182: char type = ' '; 183: Pet * pets[maxPets] = {0}; 184: int count = 0; 185: 186: while (count < maxPets) 187: { 188: // Where do you want to go today? 189: cout << "Pet type, [C]at, [D]og, [F]ish, [Q]uit: "; 190: cin >> type; 191: cin.ignore(80,'\n'); 192: 193: // Stop loop early 194: if (type == 'q' || type == 'Q') 195: break; 196: 197: switch (type) 198: { 199: case 'C': // Cat 200: case 'c': 201: { 202: pets[count] = new Cat; 203: break; 204: } 205: case 'D': // Dog 206: case 'd': 207: { 208: pets[count] = new Dog; 209: break; 210: } 211: case 'F': // Fish 212: case 'f': 213: { 214: pets[count] = new Fish; 215: break; 216: } 217: default: 218: continue; // can be used in switch 219: } 220: pets[count]->Query(); 221: count++; 222: } 223: 224: // List pets - don't need derived classes for this 225: cout << endl << "Pet Names" << endl; 226: for (int i = 0; i < count; i++) 227: { 228: cout << pets[i]->GetName(); 229: cout << endl; 230: } 231: 232: // Print characteristics - rely on virtual functions 233: cout << endl << "Characteristics" << endl; 234: for (i = 0; i < count; i++) 235: pets[i]->Print(); 236: 237: // Tidy up storage 238: for (i = 0; i < count; i++) 239: delete pets[i]; 240: }
OUTPUT
Pet type, [C]at, [D]og, [F]ish, [Q]uit: cat What is your pet Cat's name? Tibbles Does your cat Tibbles scratch? no, never has Pet type, [C]at, [D]og, [F]ish, [Q]uit: d What is your pet Dog's name? Ross Does your dog Ross bark? Yes Pet type, [C]at, [D]og, [F]ish, [Q]uit: f What is your pet Fish's name? Wanda Is your fish Wanda tropical? yes Pet type, [C]at, [D]og, [F]ish, [Q]uit: p Pet type, [C]at, [D]og, [F]ish, [Q]uit: q Pet Names Tibbles Ross Wanda Characteristics Cat : Tibbles - Scratches: No Dog : Ross - Barks: Yes Fish : Wanda - Tropical
Description
1: Comment refers to the source filename.
2: Comment to describe the program.
3: The program description continues.
4: The program description continues.
5: Blank lines help to make the program more readable.
6: Include the header for the library of stream output functions.
7: Include the header for the library of string handling functions.
8: Blank lines help to make the program more readable.
9: A comment helps separate the different classes.
10: A title for the following class.
11: A blank comment can also be used for appearance.
12: A line to declare a class called Pet.
13: All classes start with an opening brace.
14: All members after this label will be declared public.
15: The destructor for Pet is shown with the ~ character. It is declared virtual.
16: The destructor function is coded inline. The function starts with an opening brace.
17: Delete the character string pointed to by name.
18: All functions end with a closing brace.
19: A function Print() is declared that will not change the class members.
20: A function Query() is declared. This is allowed to change class members.
21: A function GetName() is declared that will not change class members.
22: All functions start with opening braces. This is declared inline.
23: name might not have a string attached, but the constructor ensures it is zeroed.
24: If name did have a string, return it.
25: A single statement if-else does not need braces surrounding the statement.
26: Return a blank string if no name has been set.
27: A closing brace ends all functions.
28: All members following this label will be protected.
29: This virtual function has not been defined and is known as a pure virtual function.
30: QueryDetails() is also a pure virtual function.
31: There is no definition for GetPetType().
32: The default constructor for the Pet class.
33: A comment helps explain an unusual coding feature.
34: An inline function starts with a closing brace.
35: Pointers should always be initialized. A valid pointer can never be zero.
36: Functions always end with closing braces.
37: All members following this label will be private.
38: A pointer to a character string initially does not own any storage.
39: All class declarations end with both a closing brace and a semicolon.
40: The function Print() belonging to the Pet class is defined.
41: All functions start with an opening brace.
42: Output the type of pet, using a virtual function so that each class can output its name.
43: Check the validity of a character pointer before using.
44: name is a member of this class, so it needs no special function to access it.
45: Call a virtual function to get details that differ by derived type.
46: Output a newline sequence.
47: All functions end with a closing brace.
48: Blank lines help you make the code more readable.
49: Define the nonvirtual function Query.
50: All functions start with an opening brace.
51: Declare a temporary character string much bigger than expected input.
52: Ask for user input, using a virtual function to customize the request for each class.
53: Get the name into a temporary string.
54: If the name already points at a string, delete it.
55: Delete the current string to recover the memory.
56: Create a dynamic memory allocation just big enough to hold the string and its terminator.
57: Copy the temporary name into the class storage.
58: Call a virtual function to get details specific to the actual class.
59: All functions end with a closing brace.
60: Blank lines help to make the program more readable.
61: A comment to mark the start of a new class.
62: A comment to identify which class is now being defined.
63: Empty comments can enhance the appearance of the program.
64: Class Cat builds the functionality of class Pet.
65: Class definitions start with an opening brace.
66: All members following this label will be public.
67: The constructor for cat can optionally take a parameter.
68: A function always starts with an opening brace.
69: A constructor should always initialize the members.
70: A function always ends with a closing brace.
71: All the functions following this label will be protected.
72: This class is going to define the PrintDetails() function.
73: This class is going to define the QueryDetails() function.
74: This class defines the GetPetType() function.
75: All functions start with an opening brace.
76: This function returns the literal string Cat.
77: All functions end with a closing brace.
78: All members following this label will be private.
79: A private data member that is an integer.
80: All class definitions end with a closing brace and a semicolon.
81: Blank lines make the program more readable.
82: Define the function PrintDetails(). This version belongs to Cat.
83: All functions start with an opening brace.
84: Output extra details of Cat class.
85: All functions end with a closing brace.
86: Blank lines help to make the program more readable.
87: Define the function QueryDetails().
88: All functions start with an opening brace.
89: Declare a character variable to test the input.
90: Query the user for information. Customize the output with a call for base class information.
91: Ask for an answer that takes just the first character.
92: Ignore the input up until the newline character.
93: If the answer is yes. . .
94: Set the member flag to true.
95: If the answer is no. . .
96: Set the member flag to false.
97: All functions end with a closing brace.
98: Blank lines help to make the program more readable.
99: A comment to mark the start of a new class.
100: A comment to identify which class is now being defined.
101: Empty comments can enhance the appearance of the program.
102: Blank lines help to make the program more readable.
103: Class Dog builds the functionality of class Pet.
104: Class definitions start with an opening brace.
105: All members following this label will be public.
106: The constructor for Dog can optionally take a parameter.
107: A function always starts with an opening brace.
108: A constructor should always initialize the members.
109: A function always ends with a closing brace.
110: All functions following this label will be protected.
111: This class is going to define the PrintDetails() function.
112: This class is going to define the QueryDetails() function.
113: This class defines the GetPetType() function.
114: All functions start with an opening brace.
115: This function returns the literal string Dog.
116: All functions end with a closing brace.
117: All members following this label will be private.
118: A private data member that is an integer.
119: All class definitions end with a closing brace and a semicolon.
120: Blank lines make the program more readable.
121: Define the function PrintDetails(). This version belongs to Cat.
122: All functions start with an opening brace.
123: Output extra details of Dog class.
124: All functions end with a closing brace.
125: Blank lines help to make the program more readable.
126: Define the function QueryDetails().
127: All functions start with an opening brace.
128: Declare a character variable to test the input.
129: Query the user for information. Customize the output with a call for base class information.
130: Ask for an answer that takes just the first character.
131: Ignore the input up until the newline character.
132: If the answer is yes. . .
133: Set the member flag to true.
134: If the answer is no. . .
135: Set the member flag to false.
136: All functions end with a closing brace.
137: Blank lines help to make the program more readable.
138: A comment to mark the start of a new class.
139: A comment to identify which class is now being defined.
140: Empty comments can enhance the appearance of the program.
141: Class Fish builds the functionality of class Pet.
142: Class definitions start with an opening brace.
143: All members following this label will be public.
144: The constructor for Fish can optionally take a parameter.
145: A function always starts with an opening brace.
146: A constructor should always initialize the members.
147: A function always ends with a closing brace.
148: All the functions following this label will be protected.
149: This class is going to define the PrintDetails() function.
150: This class is going to define the QueryDetails() function.
151: This class defines the GetPetType() function.
152: All functions start with an opening brace.
153: This function returns the literal string Fish.
154: All functions end with a closing brace.
155: All members following this label will be private.
156: A private data member that is an integer.
157: All class definitions end with a closing brace and a semicolon.
158: Define the function PrintDetails(). This version belongs to Fish.
159: All functions start with an opening brace.
160: Output extra details of Cat class.
161: All functions end with a closing brace.
162: Blank lines help to make the program more readable.
163: Define the function QueryDetails().
164: All functions start with an opening brace.
165: Declare a character variable to test the input.
166: Query the user for information. Customize the output with a call for base class information.
167: Ask for an answer that takes just the first character.
168: Ignore the input up until the newline character.
169: If the answer is yes. . .
170: Set the member flag to true.
171: If the answer is no. . .
172: Set the member flag to false.
173: All functions end with a closing brace.
174: Blank lines make the program more readable.
175: A comment to divide the code.
176: A comment to tell the programmer that he has found the main procedure.
177: Blank comments can enhance the appearance of the program.
178: Blank lines make the program more readable.
179: The start of the main procedure.
180: All functions start with an opening brace.
181: Define a constant for the maximum number of entries.
182: Initialize a temporary input character.
183: Define an array of pointers to the Pet class.
184: A counter to record how many pets have been entered.
185: Blank lines make the program more readable.
186: Do the following statements as long as the number of entries do not exceed the array capacity.
187: A while loop of multiple statements is delimited by an opening brace.
188: Not all comments serve a useful purpose.
189: Prompt the user for a selection.
190: Store the first character of a users answer.
191: Ignore any spare input after the first character.
192: Blank lines make the program more readable.
193: Comments can explain why code is written.
194: Test the input to see whether the user has finished.
195: Leave the loop if the if test is true.
196: Blank lines make the program more readable.
197: Avoid complex if statements by using the switch statement.
198: switch statements are enclosed in braces.
199: Execute from here if type is 'C'.
200: Execute from here if type is 'c'. The first case will fall through.
201: case statements can be enclosed in a block.
202: Make an object of type Cat and store it in a general Pet pointer.
203: Break out of the rest of the switch statement.
204: End of case block.
205: case for Dog.
206: case for Dog.
207: case statements can be enclosed in a block.
208: Make an object of type Dog and store it in a general Pet pointer.
209: Break out of the rest of the switch statement.
210: End of case block.
211: case for Fish
212: case for Fish
213: case statements can be enclosed in a block.
214: Make an object of type Fish and store it in a general Pet pointer.
215: Break out of the rest of the switch statement.
216: End of case block.
217: If the input does not match any planned case, do the following.
218: Executing continue will go around the loop, skipping the remaining code.
219: End the switch statement.
220: Call the input function for the new object. Because it contains virtual function calls, different code for each type will be called.
221: Increment the number of valid objects count.
222: End the while loop compound statement.
223: Blank lines help make the program more readable.
224: Comment to help understand the following processing.
225: Output a title.
226: for as many items in the container.
227: for loops performing multiple statements enclose them in braces.
228: Output the pet's name by using a nonvirtual function belonging to the base class.
229: A newline character sequence is output.
230: End of the for loop is denoted by the closing brace.
231: Blank lines make the program more readable.
232: A comment to explain the following processing.
233: Output a title.
234: for all the items in the container.
235: A for loop can execute a single statement.
236: Blank lines make the code more readable.
237: A comment to explain the following processing.
238: for each item in the container.
239: Delete the storage associated with the pointer.
240: The main function ends with a closing brace.
29: Classes containing pure virtual functions are known as abstract classes.
69: If no base constructor is explicitly called in the initialization list, the default base constructor is called.
71: Protected members are only visible to this class and derived classes.
76: Visual C++ can't access the actual class name.
183: An array of pointers takes up a small amount of space compared to the classes, and derived classes might take up much more storage than a base class.
201: case statements must be enclosed in braces if they declare a variable.
203: Meeting a case statement does not cause a branch out of the switch statement.
226: The scope of local variable i is the block containing for, not the for loop itself. Note the following for loops.
235: Print() contains virtual functions that will execute code specific to each object's class.
239: Because the base class destructor is virtual, the correct destructor will be called even though the pointer belongs to the base class.