Освой самостоятельно С++ за 21 день.
Шрифт:
92: String::~String
93: {
94: ASSERT(Invariants);
95: delete [] itsString;
96: itsLen = 0;
97: }
96:
99: // оператор выполняет сравнение, освобождает занятую
100: // память, а затем копирует строку и ее размер
101: String& String::operator=(const String & rhs)
102: {
103: ASSERT(Invariants);
104: if (this == &rhs)
105: return *this;
106: delete [] itsString;
107: itsLen=rhs,GetLen;
108: itsString = new char[itsLen+1];
109: for (int i = 0; i<itsLen;i++)
110: itsString[i] = rhs[i];
111: itsString[itsLen] = '\0';
112: ASSERT(Invariants);
113: return *this;
114: }
115:
116: //
117: char & String::operator[](int offset)
118: {
119: ASSERT(Invariants);
120: if (offset > itsLen)
121: {
122: ASSERT(Invariants);
123: return itsString[itsLen-1];
124: }
125: else
126: {
127: ASSERT(Invariants);
128: return itsString[offset];
129: }
130: }
131: // константный оператор индексирования
132: char String::operator[](int offset) const
133: {
134: ASSERT(Invariants);
135: char retVal;
136: if (offset > itsLen)
137: retVal = itsString[itsLen-1];
138: else
139: retVal = itsString[offset];
140: ASSERT(Invariants);
141: return retVal;
142: }
143: bool String::Invariants const
144: {
145: #ifdef SHOW_INVARIANTS
146: cout << "Invariants Tested";
147: #endif
148: return ( (itsLen && itsString) ||
149: (!itsLen && !itsString) );
150: }
151: class Animal
152: {
153: public:
154: Animal:itsAge(1),itsName("John Q. Animal")
155: { ASSERT(Invariants);}
156: Animal(int, const String&);
157: ~Animal{ }
158: int GetAge { ASSERT(Invariants); return itsAge;}
159: void SetAge(int Age)
160: {
161: ASSERT(Invariants);
162: itsAge = Age;
163: ASSERT(Invariants);
164: }
165: String& GetName
166: {
167: ASSERT(Invariants);
168: return itsName;
169: }
170: void SetName(const String& name)
171: {
172: ASSERT(Invariants);
173: itsName = name;
174: ASSERT(Invariants);
175: }
176: bool Invariants;
177: private:
178: int itsAge;
179: String itsName;
180: };
181:
182: Animal::Animal(int age, const String& name):
183: itsAge(age),
184: itsName(name)
185: {
186: ASSERT(Invariants);
187: }
188:
189: bool Animal::Invariants
190: {
191: #ifdef SHOW_INVARIANTS
192: cout << "Invariants Tested";
193: #endif
194: return (itsAge > 0 && itsName.GetLen);
195: }
196:
197: int main
198: {
199: Animal sparky(5, "Sparky");
200: cout << "\n" << sparky.GetName.GetString << " is ";
201: cout << sparky.GetAge << " years old. ";
202: sparky.SetAge(8):
203: cout << "\n" << sparky.GetName. GetString << " is ";
204: cout << sparky.GetAge << " years old. ";
205: return 0;
206: }
Результат:
String OK String OK String OK String OK String OK String OK String OK
String OK String OK Animal OK String OK Animal OK
Sparky is Animal OK 5 years old. Animal OK Animal OK
Animal OK Sparky is Animal OK 8 years old. String OK
Анализ: В строках 9—15 определяется макрос assert. Если лексема DEBUG определена и макрос assert возвратит в результате операции сравнения значение FALSE, будет выведено сообщение об ошибке.
В строке 39 объявляется функция-член Invariants класса String, а ее определение занимает строки 143—150. Конструктор объявляется в строках 49—55, а в строке 54, после того как объект полностью построен, вызывается функция-член Invariants, чтобы подтвердить правомочность этой конструкции.
Этот алгоритм повторен для других конструкторов, а для деструктора функция- член Invariants вызывается только перед тем, как удалить объект. Остальные методы класса вызывают функцию Invariants перед выполнением любого действия, а затем еще раз перед возвратом из функции. В этом проявляется отличие функций- членов от конструкторов и деструкторов: функции-члены всегда работают с реальными объектами и должны оставить их таковыми по завершению выполнения функции.
В строке 176 класс Animal объявляет собственный метод Invariants, выполняемый в строках 189—195. Обратите внимание на строки 155, 158, 161 и 163: подставляемые функции также могут вызывать метод Invariants.