Джесс Либерти - Освой самостоятельно С++ за 21 день.
- Название:Освой самостоятельно С++ за 21 день.
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Джесс Либерти - Освой самостоятельно С++ за 21 день. краткое содержание
В книге широко представлены возможности новейшей версии программного продукта Microsoft Visual C++. Подробно описаны средства и подходы программирования современных профессиональных приложений. Материалы книги дополнены многочисленными демонстрационными программами, в процессе разработки которых максимально используются возможности программных инструментов Microsoft Visual Studio. Особое внимание уделено новинкам версии 6.0 и новейшим технологиям объектно-ориентированного программирования, включая использование библиотеки MFC и шаблонов классов, а также создание связанных списков. Отдельное занятие посвящено вопросам объектно-ориентированного анализа и проектирования приложений. Подробно рассмотрены все средства и подходы конструирования собственных пользовательских классов.
Книга рассчитана на широкий круг читателей, интересующихся современными проблемами программирования.
Освой самостоятельно С++ за 21 день. - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
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
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().
Печать промежуточных значений
Не исключено, что в дополнение к возможности с помощью макроса assert() убедиться в истинности некоторого тестируемого выражения вы захотите вывести на экран текущие значения указателей, переменных и строк. Это может быть полезно для проверки ваших предположений насчет некоторых аспектов работы программы, а также при поиске ошибок в циклах. Реализация этой идеи показана в листинге 21.6.
Листинг 21.6. Вывод значений в режиме отладки
1: // Листинг 21.6. Вывод значений в режиме отладки
2: #include
3: #define DEBUG
4:
5: #ifndef DEBUG
6: #define PRINT(x)
7: #else
8: #define PRINT(x) \
9: cout << #x << ":\t" << x << endl;
10: #endif
11:
12: enum bool { FALSE, TRUE } ; 13:
14: int main()
15: {
16: int x = 5;
17: long у = 738981;
18: PRINT(x);
19: for (int i = 0; i < x; i++)
20: {
21: PRINT(i);
22: }
23:
24: PRINT (у);
25: PRINT("Hi,");
26: int *px = &x;
27: PRINT(px);
28: PRINT (*px);
29: return 0;
30: }
Результат:
x: 5
i: 0
i: 1
i: 2
i: 3
i: 4
у: 73898
"Hi.": Hi.
px: 0x2100
*px: 5
Анализ:Макрос PRINT(x) (строки 5—10) реализует вывод текущего значения переданного параметра. Обратите внимание, что сначала объекту cout передается сам параметр, взятый в кавычки, т.е., если вы передадите параметр x, объект cout примет "x".
Затем объект cout принимает заключенную в кавычки строку ":\t", которая обеспечивает печать двоеточия и табуляции. После этого объект cout принимает значение параметра (x), а объект endl выполняет переход на новую строку и очищает буфер.
Обратите внимание, что у вас вместо значения 0x2100 может быть выведено другое число.
Уровни отладки
В больших и сложных проектах вам, возможно, понадобится больше рычагов управления для отлаживания программы, чем просто подключение и отключение режима отладки (путем определения лексемы DEBUG). Вы можете определять уровни отладки и выполнять тестирование для этих уровней, принимая решение о том, какие макрокоманды использовать, а какие - удалить.
Чтобы определить уровень отладки, достаточно после выражения #define DEBUG указать номер. Хотя число уровней может быть любым, обычная система должна иметь четыре уровня: HIGH (высокий), MEDIUM (средний), LOW (низкий) и NONE (никакой). В листинге 21.7 показано, как это можно сделать, на примере классов String и Animal из листинга 21.5.
Листинг 21.7. Уровни отладки
1: enum LEVEL { NONE, LOW, MEDIUM, HIGH } ;
2: const int FALSE = 0;
3: const int TRUE = 1;
4: typedef int bool;
5:
6: #define DEBUGLEVEL HIGH
7:
8: #include
9: #include
10:
11: #if DEBUGLEVEL < LOW // должен быть средний или высокий
12: #define ASSERT(x)
13: #else
14: #define ASSERT(x)
15: if (!(x))
16: {
17: cout << "ERROR!! Assert " << #x << " failed\n";
18: cout << " on line " << __LINE__ << "\n";
19: cout << " in file " << FILE << "\n";
20: }
21: #endif
22:
23: #if DEBUGLEVEL < MEDIUM
24: #define EVAL(x)
25: #else
26: #define EVAL(x)
27: cout << #x << ":\t" << x << andl;
28: #endif
29:
30: #if DEBUGLEVEL < HIGH
31: #define PRINT(x)
32: #else
33: #define PRINT(x)
34: cout << x << endl;
35: #endif
36:
37:
38: class String
39: {
40: public:
41: // конструкторы
42: String();
43: String(const char *const);
44: String(const String &);
45: ~String();
46:
47: char & operator[](int offset);
48: char operator[](int offset) const;
49:
50: String & operator= (const String &);
51: int GetLen()const { return itsLen; }
52: const char >> GetString() const
53: { return itsString; }
54: bool Invariants() const;
55:
56: private:
57: String (int); // закрытый конструктор
58: char * itsString;
59: unsigned short itsLen;
60: };
61:
62: // стандартный конструктор создает строку нулевой длины
63: String::String()
64: {
65: itsString = new char[1];
66: itsString[0] = '\0';
67: itsLen=0;
68: ASSERT(Invariants());
69: }
70:
71: // закрытый (вспомогательный) конструктор, используемый
Читать дальшеИнтервал:
Закладка: