А. Пол
ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ НА C++
Книга Айры Пола, автора многих популярных изданий по С и C++, не является ни учебником по C++, ни курсом по объектно-ориентированному программированию (ООП) «вообще», хотя может быть полезна и в этих двух качествах. Задача книги (точно отраженная в названии) совершенно конкретна: научить читателя писать на C++ объектно-ориентированные программы. Для многих абстрактных идей и понятий ООП в C++ существуют конкретные воплощающие их конструкции. В каждой главе автор вводит и объясняет очередную «порцию» таких конструкций, демонстрирует технику их эффективного использования. В некоторых случаях возникающие перед программистом на C++ проблемы не могут быть непосредственно решены средствами языка. Здесь на помощь приходят разнообразные приемы, не владея которыми трудно программировать на C++ реальные задачи. Такие приемы поясняются автором на многочисленных примерах, причем наиболее показательные программы подвергаются тщательному разбору.
Много внимания на страницах книги уделено самым последним дополнениям C++: стандартной библиотеке шаблонов (STL), пространствам имен (namespaces), механизму идентификации типов во время выполнения (RTTI), явным приведениям типов (cast-операторам) и другим.
Книга в первую очередь рассчитана на программистов, желающих получить ясное представление о парадигме объектно-ориентированного программирования в C++. Издание также будет полезно преподавателям, студентам и всем, кто хочет освоить объектно-ориентированное программирование на C++.
Содержание
Предисловие |
13 |
Глава 1 |
|
Зачем нужно объектно-ориентированное программирование на C++? |
17 |
1.1. Объектно-ориентированное программирование |
18 |
1.2. Пример программы на C++ |
19 |
1.3. Инкапсуляция и расширяемость типов |
21 |
1.4. Конструкторы и деструкторы |
23 |
1.5. Перегрузка |
25 |
1.6. Шаблоны и обобщенное программирование |
27 |
1.7. Стандартная библиотека шаблонов (STL) |
29 |
1.8. Наследование |
30 |
1.9. Полиморфизм |
32 |
1.10. Исключения в C++ |
34 |
1.11. Преимущества объектно-ориентированного программирования |
35 |
Глава 2 |
|
Собственные типы данных и инструкции |
37 |
2.1. Элементы программы |
37 |
2.1.1. Комментарии |
38 |
2.1.2. Ключевые слова |
38 |
2.1.3. Идентификаторы |
39 |
2.1.4. Литералы |
39 |
2.1.5. Операторы и знаки пунктуации |
41 |
2.2. Ввод-вывод |
41 |
2.3. Структура программы |
42 |
2.4. Простые типы |
44 |
2.4.1. Инициализация |
45 |
2.5. Традиционные преобразования |
46 |
2.6. Перечислимые типы |
49 |
2.7. Выражения |
50 |
2.8. Инструкции |
53 |
2.8.1. Присваивание и выражения |
53 |
2.8.2. Составная инструкция |
55 |
2.8.3. Инструкции if и if-else |
55 |
2.8.4. Инструкция while |
56 |
2.8.5. Инструкция for |
56 |
2.8.6. Инструкция do |
57 |
2.8.7. Инструкции break и continue |
58 |
2.8.8. Инструкция switch |
59 |
2.8.9. Инструкция goto |
60 |
2.9. Практические замечания |
61 |
Резюме |
61 |
Упражнения |
63 |
Глава 3 |
|
Функции и указатели |
69 |
3.1. Функции |
69 |
3.1.1. Вызов функции |
69 |
3.2. Определение функции |
70 |
3.3. Инструкция return |
71 |
3.4. Прототипы функций |
72 |
3.5. Аргументы по умолчанию |
74 |
3.6. Перегрузка функций |
75 |
3.7. Встраивание |
76 |
3.8. Область видимости и класс памяти |
77 |
3.8.1. Класс памяти auto |
78 |
3.8.2. Класс памяти register |
79 |
3.8.3. Класс памяти extern |
79 |
3.8.4. Класс памяти static |
81 |
3.8.5. Таинства компоновки |
82 |
3.9. Пространства имен |
82 |
3.10. Типы указателей |
83 |
3.10.1. Определение адреса и разыменование |
84 |
3.10.2. Вызов по ссылке на основе указателей |
84 |
3.11. Применение void |
86 |
3.12. Массивы и указатели |
86 |
3.12.1. Индексирование |
87 |
3.12.2. Инициализация |
88 |
3.13. Связь между массивами и указателями |
88 |
3.14. Передача массивов функциям |
89 |
3.15. Объявления ссылок и вызов по ссылке |
90 |
3.16. Проверка утверждений и корректность программы |
92 |
3.17. Строки: соглашение о char* |
94 |
3.18. Многомерные массивы |
95 |
3.19. Операторы свободной памяти new и delete |
95 |
3.20. Практические замечания |
98 |
3.20.1. void* и reinterpret_cast |
98 |
3.20.2. Замена объявлений static extern |
98 |
Резюме |
99 |
Упражнения |
100 |
Глава 4 |
|
Реализация АТД в базовом языке |
107 |
4.1. Агрегатный тип struct |
107 |
4.2. Оператор указателя структуры |
109 |
4.3. Пример: стек |
109 |
4.4. Объединения |
113 |
4.5. Комплексные числа |
115 |
4.6. Пример: флеш |
116 |
4.7. Битовые поля |
120 |
4.8. Пример: двумерные динамические массивы |
121 |
4.9. Практические замечания |
124 |
Резюме |
124 |
Упражнения |
125 |
Глава 5 |
|
Сокрытие данных и функции-члены класса |
131 |
5.1. Функции-члены класса |
132 |
5.2. Доступ: закрытый и открытый |
135 |
5.3. Классы |
136 |
5.4. Область видимости класса |
138 |
5.4.1. Оператор разрешения области видимости :: |
138 |
5.4.2. Вложенные классы |
139 |
5.5. Пример: пересмотрим флеш |
140 |
5.6. Статические члены данных |
142 |
5.7. Указатель this |
143 |
5.8. Функции-члены типа static и const |
144 |
5.8.1. Изменчивость (mutable) |
146 |
5.9. Контейнеры и доступ к их содержимому |
147 |
5.10. Практические замечания |
149 |
Резюме |
150 |
Упражнения |
151 |
Глава 6 |
|
Создание и уничтожение объектов |
155 |
6.1. Классы с конструкторами |
156 |
6.1.1. Конструктор по умолчанию |
157 |
6.1.2. Инициализатор конструктора |
157 |
6.1.3. Конструкторы как преобразования |
158 |
6.2. Создание динамического стека |
159 |
6.2.1. Копирующий конструктор |
160 |
6.3. Классы с деструкторами |
161 |
6.4. Пример: динамически размещаемые строки |
162 |
6.5. Класс vect |
166 |
6.6. Члены данных, являющиеся классами |
168 |
6.7. Пример: односвязный список |
169 |
6.8. Двумерные массивы |
173 |
6.9. Многочлен как связный список |
174 |
6.10. Строки, использующие семантику ссылок |
179 |
6.11. В отсутствии конструктора, копирующий конструктор и другие |
181 |
тайны |
|
6.11.1. Деструкторы: некоторые детали |
182 |
6.12. Практические замечания |
182 |
Резюме |
183 |
Упражнения |
184 |
Глава 7 |
|
Ad hoc полиморфизм |
191 |
7.1. Преобразования АТД |
192 |
7.2. Перегрузка и выбор функций |
193 |
7.3. Дружественные функции |
195 |
7.4. Перегрузка операторов |
197 |
7.5. Перегрузка унарных операторов |
199 |
7.6. Перегрузка бинарных операторов |
201 |
7.7. Перегрузка операторов присваивания и индексирования |
202 |
7.8. Многочлены: что можно ждать от типа и языка |
206 |
7.9. Перегруженные операторы ввода-вывода « и » |
207 |
7.10. Перегрузка оператора () для индексирования |
208 |
7.11. Операторы указателей |
210 |
7.11.1. Указатель на член класса |
212 |
7.12. Перегрузка new и delete |
214 |
7.13. Практические замечания |
216 |
7.13.1. Соответствие сигнатуре |
217 |
Резюме |
218 |
Упражнения |
220 |
Глава 8 |
|
Перебор: итераторы и контейнеры |
227 |
8.1. Перебор |
227 |
8.2. Итераторы |
228 |
8.3. Пример:quicksort() |
229 |
8.4. Дружественные классы и итераторы |
232 |
8.5. Обобщенное программирование с использованием void* |
234 |
8.6. Список и итератор списка |
236 |
8.7. Практические замечания |
239 |
Резюме |
240 |
Упражнения |
241 |
Глава 9 |
|
Шаблоны, обобщенное программирование и STL |
245 |
9.1. Шаблонный класс stack |
245 |
9.2. Шаблоны функций |
247 |
9.2.1. Соответствие сигнатуре и перегрузка |
249 |
9.3. Шаблоны классов |
250 |
9.3.1. Друзья |
250 |
9.3.2. Статические члейы |
250 |
9.3.3. Аргументы шаблона класса |
—— |
|
250 |
9.4. Параметризация класса vector |
251 |
9.5. Параметризация quicksort^) |
254 |
9.6. Параметризованное дерево двоичного поиска |
255 |
9.7. STL |
259 |
9.8. Контейнеры |
260 |
9.8.1. Последовательные контейнеры |
262 |
9.8.2. Ассоциативные контейнеры |
263 |
9.8.3. Адаптеры контейнеров |
265 |
9.9. Итераторы |
267 |
9.9.1. Итераторы istream_iterator и ostream_iterator |
268 |
9.9.2. Адаптеры итераторов |
269 |
9.10. Алгоритмы |
269 |
9.10.1. Алгоритмы сортировки |
270 |
9.10.2. Не изменяющие последовательность алгоритмы |
270 |
9.10.3. Изменяющие последовательность алгоритмы |
271 |
9.10.4. Численные алгоритмы |
272 |
9.11. Функции |
273 |
9.12. Адаптеры функций |
275 |
9.13. Практические замечания |
276 |
Резюме |
276 |
Упражнения |
277 |
Глава 10 |
|
Наследование |
281 |
10.1. Производный класс |
282 |
10.2. Преобразования типов и видимость |
284 |
10.3. Повторное использование кода: класс двоичного дерева |
286 |
10.4. Виртуальные функции |
289 |
10.5. Абстрактные базовые классы |
293 |
10.6. Шаблоны и наследование |
297 |
10.7. Множественное наследование |
299 |
10.8. Наследование и проектирование |
301 |
10.8.1. Форма подтипов |
302 |
10.9. Идентификация типа на этапе выполнения |
304 |
10.10. Практические замечания |
305 |
Резюме |
306 |
Упражнения |
307 |
Глава 11 |
|
Исключения |
311 |
11.1. Использование assert.h |
311 |
11.2. Использование signal.h |
312 |
11.3. Исключения C++ |
316 |
11.4. Запуск исключений |
317 |
11.4.1. Перезапуск исключений |
318 |
11.4.2. Выражения исключений |
319 |
11.5. Пробные блоки try |
319 |
11.6. Обработчики |
320 |
11.7. Спецификация исключения |
321 |
11.8. terminate() и unexpected() |
321 |
11.9. Пример кода с исключениями |
322 |
11.10. Стандартные исключения и их использование |
324 |
11.11. Практические замечания |
325 |
Резюме |
326 |
Упражнения |
328 |
Глава 12 |
|
ООП на C++ |
331 |
12.1. Требования к языку ООП |
331 |
12.2. АТД в не-ООП языках |
332 |
12.3. Клиенты и производители |
333 |
12.4. Повторное использование кода и наследование |
334 |
12.5. Полиморфизм |
335 |
12.6. Сложность языка |
336 |
12.7. Успех ООП на C++ |
337 |
12.8. Платонизм: проектирование «tabula rasa» |
338 |
12.9. Принципы проектирования |
340 |
12.10. Схемы, диаграммы и инструменты |
341 |
12.11. Штампы проектирования |
343 |
12.12. C++: критика |
343 |
Резюме |
345 |
Упражнения |
346 |
Приложение А |
|
Коды символов ASCII |
349 |
Приложение В |
|
Приоритет и порядок выполнения операторов |
351 |
Приложение С |
|
Руководство по языку |
353 |
С.1. Структура программы |
353 |
С.2. Лексические элементы |
353 |
С.2.1. Комментарии |
354 |
С.2.2. Идентификаторы |
354 |
С.2.3. Ключевые слова |
355 |
С.3. Константы |
355 |
С.4. Объявления и правила области видимости |
357 |
С.5. Пространства имен |
359 |
С.6. Правила компоновки |
360 |
С.7. Типы |
362 |
С.8. Приведения и правила преобразований |
364 |
С.9. Выражения и операторы |
367 |
С.9.1. Выражения sizepf |
367 |
С.9.2. Выражения автоинкремента и автодекремента |
368 |
С.9.3. Арифметические выражения |
368 |
С.9.4. Выражения отношения, равенства и логические выражения |
368 |
С.9.5. Выражения присваивания |
369 |
С.9.6. Выражения с запятой |
370 |
С.9.7. Условные выражения |
370 |
С.9.8. Выражения с битовыми операторами |
371 |
С.9.9. Выражения с определением адреса и обращением по адресу |
371 |
С.9.10. Выражения с new и delete |
372 |
С.9.11. Другие выражения |
374 |
С.10. Инструкции |
375 |
С.10.1. Инструкции-выражения |
376 |
С.10.2. Составная инструкция |
376 |
С.10.3. Инструкции if и if-else |
377 |
С.10.4. Инструкция while |
377 |
С.10.5. Инструкция for |
377 |
С.10.6. Инструкция do |
378 |
С.10.7. Инструкции break и continue |
379 |
С.10.8. Инструкция switch |
379 |
С.10.9. Инструкция goto |
380 |
С.10.10. Инструкция return |
381 |
С.10.11. Инструкция-объявление |
381 |
С.11. Функции |
381 |
С.11.1. Прототипы |
382 |
С.11.2. Вызов по ссылке |
383 |
С.11.3. Встроенные функции |
383 |
С.11.4. Аргументы по умолчанию |
383 |
С.11.5. Перегрузка |
383 |
С.11.6. Типобезопасная компоновка для функций |
385 |
С.12. Классы |
385 |
С.12.1. Конструкторы и деструкторы |
386 |
С.12.2. Функции-члены |
387 |
С.12.3. Дружественные функции |
387 |
С.12.4. Указатель this |
388 |
С. 12.5. Перегрузка операторов |
388 |
С.12.6. Функции-члены типа static и const |
390 |
С.12.7. Изменчивость (mutable) |
391 |
С.12.8. Проектирование классов |
391 |
С.13. Наследование |
391 |
С.13.1. Множественное наследование |
393 |
С.13.2. Вызов конструктора |
394 |
С.13.3. Абстрактные базовые классы |
394 |
С.13.4. Указатель на член класса |
394 |
С.13.5. Идентификация типа на этапе выполнения |
394 |
С.13.6. Виртуальные функции |
395 |
С.14. Шаблоны |
396 |
С.14.1. Параметры шаблона |
397 |
С.14.2. Шаблоны функций |
398 |
С.14.3. Друзья |
399 |
С.14.4. Статические члены |
399 |
С.14.5. Специализация |
400 |
С. 15. Исключения |
400 |
С.15.1. Запуск исключений |
401 |
С.15.2. Пробные блоки try |
402 |
С.15.3. Обработчики |
403 |
С.15.4. Спецификация исключения |
403 |
С.15.5. terminate() и unexpected() |
404 |
С.15.6. Стандартные библиотечные исключения |
404 |
С.16. Предосторожности, связанные с совместимостью |
404 |
С.16.1. Объявления вложенных классов |
405 |
С.16.2. Совместимость типов |
405 |
С.16.3. Разное |
405 |
С.17. Новые возможности C++ |
406 |
Приложение D |
|
Ввод-вывод |
407 |
D.1. Класс вывода ostream |
407 |
D.2. Форматированный вывод и iomanip.h |
408 |
D.3. Пользовательские типы: вывод |
410 |
D.4. Класс ввода istream |
412 |
D.5. Файлы |
|
413 |
D.6. Использование строк как потоков |
|
415 |
D.7. Функции и макро в ctype.h |
|
416 |
D.8. Использование состояния потока |
|
417 |
D.9. Совместное использование библиотек ввода-вывода |
419 |
|
Приложение Е |
|
|
STL и строковые библиотеки |
|
421 |
Е.1. Контейнеры |
|
421 |
Е.1.1. Последовательные контейнеры |
|
423 |
Е.1.2. Ассоциативные контейнеры |
|
423 |
Е.1.3. Адаптеры контейнеров |
|
424 |
Е.2. Итераторы |
|
426 |
Е.2.1. Категории итераторов |
|
426 |
Е.2.2. Итератор istream_iterator |
|
427 |
Е.2.3. Итератор ostream_iterator |
|
427 |
Е.2.4. Адаптеры итераторов |
|
427 |
Е.3. Алгоритмы |
|
428 |
Е.3.1. Алгоритмы сортировки |
|
428 |
Е.3.2. Не изменяющие последовательность алгоритмы |
431 |
|
Е.3.3. Изменяющие последовательность алгоритмы |
432 |
|
Е.3.4. Численные алгоритмы |
|
434 |
Е.4. Функции |
|
435 |
Е.4.1. Адаптеры функций |
|
436 |
Е.5. Распределители памяти |
|
437 |
Е.6. Строковая библиотека |
|
438 |
Е.6.1. Конструкторы |
|
439 |
Е.6.2. Функции-члены |
|
440 |
Е.6.3. Глобальные операторы |
|
443 |
Литература |
|
445 |
Предметный указатель |
|
447 |
Предметный указатель |
|
|
Символы |
->* 212, 394 |
|
, (запятая) 370 |
.* 212, 394 |
|
! 51, 369 |
/* 38, 354 |
|
!= 51 |
// 20, 38, 354 |
|
#define, директива 76, 357 |
: : 358; 375 |
|
#include, директива 357 |
< 51 |
|
& 53, 83, 371 |
<< 207, 407, 408 |
|
&& 51 |
<= 51 |
|
() 53, 198, 208, 374 |
- 198 |
|
- 53, 84, 86, 371, 374 |
= = 51 |
|
++ 54, 368 |
> 51 |
|
- 54, 368 |
>= 51 |
|
-> 109, 198, 210, 374 |
>> 208, 407, 412 |
|
?: 370 [] 53, 89, 198, 374 '
\0 24, 162, 412 {} 55, 375, 376 | | 51 - 24, 155
A abstract base class 394 abstract class 293 abstract data type 18 accessor function 150
accumulate(), функция 30, 259, 272 Ada 332, 336
adaptor 265, 424 adaptor pattern 393 address operator 83 ALGOL 343, 345 alias 90
allocate(), функция 122 allocator 437
anonymous namespace 83 area(), функция 33
array 86
array_2d, программа 123 ASCII, таблица символов 349 assert, макро 93, 311
assert.h 93, 311 assertion 92, 311
assign(), функция 22, 117 auto
класс памяти 78 ключевое слово 363
avg_arr(), функция 75 B
bad_alloc
исключение 324, 374
класс 325, 404 bad_cast
исключение 324
класс 325, 404 bad_typeid, класс 325, 404 begin(), функция 30 bitfield 120
bool, тип 51, 362, 368
break 58, 379
C call-by-reference 84 call-by-value 42, 70 calling environment 69 case 59, 379 CASE-средства 341 cast 47, 364, 385
cast away constness 48, 365 catch 34
ключевое слово 316 обработчик 320
caux 413 cctype 416 cerr 407, 413
ch_stack(), функция 111 char*, тип 94
checks.h 312 cin 412, 413
class, ключевое слово 136, 282, 391 class-responsibility-collaboration 341 client 333
clog 413 CLOS 344
close(), функция 414 COBOL 332, 343 coercion 335
comp(), функция 256 completeness 340 complex 83 complex.h 83, 360
computer assisted software engineering (CASE) 341
const 144
ключевое слово 357, 363, 390 модификатор 82 const-correctness 144
const_cast, приведение 48, 146, 365, 391
constructor 23, 148, 155, 386 initializer 157
container 110 container class 227