Система Orphus

Программирование на C++

Классика Computer Science

Автор: Коплиен Дж.
Издательство: Питер, 2004
480 страницы

Материал предоставил: В. Лаптев
Найти в магазинах
Купить в Books.Ru
Купить в издательстве "Питер"

Аннотация

Содержание
Комментарии

Аннотация

Эта книга написана для программистов, уже владеющих языком C++ и желающих поднять свою квалификацию на новый уровень. Давая представление о стиле и идиоматике языка, книга знакомит читателя с теми нетривиальными знаниями, которые опытные программисты C++ получают на личном опыте. Она показывает, что C++ можно использовать и для разработки простых абстракций данных, и для полноценной реализации абстрактных типов данных, и для объектно-ориентированного программирования различных стилей. Кроме того, в ней исследуются идиомы, не поддерживаемые напрямую на базовом уровне C++, например, функциональное и фреймовое программирование, а также расширенные методы "сборки мусора".

Содержание

Предисловие

Изучение языка программирования
О книге
Структура книги
Благодарности
От издателя перевода

Глава 1. Введение

1.1. C++ как развивающийся язык
1.2. Решение проблемы сложности при помощи идиом
1.3. Объекты для 90-х
1.4. Проектирование и язык
Литература

Глава 2. Абстракция и абстрактные типы данных

2.1. Классы
2.2. Объектная инверсия
2.3. Конструкторы и деструкторы
2.4. Подставляемые функции
2.5. Инициализация статических переменных
2.6. Статические функции классов
2.7. Область видимости и константность
2.8. Порядок инициализации глобальных объектов, констант и статических членов классов
2.9. Обеспечение константности функций классов
Логическая и физическая константность
2.10. Указатели на функции классов
2.11. Правила организации программного кода
Упражнения
Литература

Глава 3. Конкретные типы данных

3.1. Ортодоксальная каноническая форма класса
3.2. Видимость и управление доступом
3.3. Перегрузка - переопределение семантики операторов и функций
Пример перегрузки оператора индексирования
Перегрузка операторов в классах и глобальная перегрузка
3.4. Преобразование типа
3.5. Подсчет ссылок
Идиома класса-манипулятора
Экономное решение
Подсчет указателей
Реализация подсчета ссылок в существующих классах
Классы конвертов и синглетные письма
3.6. Операторы new и delete
3.7. Отделение инициализации от создания экземпляра
Упражнения
Литература

Глава 4. Наследование

4.1. Простое наследование
Настройка операций класса Complex для семантики класса Imaginary
Использование кода базового класса в производном классе
Изменение функций производного класса для повышения эффективности
4.2. Видимость и управление доступом
Вертикальное управление доступом при наследовании
Горизонтальное управление доступом при наследовании
Создание экземпляров путем наследования и управления доступом
4.3. Конструкторы и деструкторы
Порядок выполнения конструкторов и деструкторов
Передача параметров конструкторам базовых классов и внутренних объектов
4.4. Преобразование указателей на классы
4.5. Селектор типа
Упражнения
Литература

Глава 5. Объектно-ориентированное программирование

5.1. Идентификация типов на стадии выполнения и виртуальные функции
5.2. Взаимодействие деструкторов и виртуальные деструкторы
5.3. Виртуальные функции и видимость
5.4. Чисто виртуальные функции и абстрактные базовые классы
5.5. Классы конвертов и писем
Классы конвертов и делегированный полиморфизм
Имитация виртуальных конструкторов
Другой подход к виртуальным конструкторам
Делегирование и классы конвертов
Итераторы и курсоры
5.6. Функторы
Функциональное и аппликативное программирование
5.7. Множественное наследование
Пример абстракции окна
Неоднозначность при вызове функций класса
Неоднозначность в данных
Виртуальные базовые классы
Предотвращение лишних вызовов функций виртуальных базовых классов
Виртуальные функции
Преобразование указателей на объекты при множественном наследовании
5.8. Каноническая форма наследования
Упражнения
Пример итератора очереди
Простые классы счетов для банковского приложения
Литература

Глава 6. Объектно-ориентированное проектирование

6.1. Типы и классы
6.2. Основные операции объектно-ориентированного проектирования
6.3. Объектно-ориентированный и доменный анализ
Причины увеличения объема проектирования
Способы расширения абстракций
Балансировка архитектуры
Результаты хорошей балансировки архитектуры
6.4. Отношения между объектами и классами
Отношения ''IS-A''
Отношения ''HAS-A''
Отношения ''SES-A''
Отношения ''CREATES-A''
Контекстное изучение отношений между объектами и классами
Графическое представление отношений между объектами и классами
6.5. Субтипы, наследование и перенаправление
Наследование ради наследования - ошибка потери субтипов
Случайное наследование - омонимы в мире типов
Потребность в функциях классов с ''истинной'' семантикой
Наследование и независимость классов
6.6. Практические рекомендации
Упражнения
Литература

Глава 7. Многократное использование программ и объекты

7.1. Об ограниченности аналогий
7.2. Многократное использование архитектуры
7.3. Четыре механизма многократного использования кода
7.4. Параметризованные типы, или шаблоны
7.5. Закрытое наследование и многократное использование
7.6. Многократное использование памяти
7.7. Многократное использование интерфейса
7.8. Многократное использование, наследование и перенаправление
7.9. Архитектурные альтернативы для многократного использования исходных текстов
7.10. Общие рекомендации относительно многократного использования кода
Упражнения
Литература

Глава 8. Прототипы

8.1. Пример с прототипами класса Employee
8.2. Прототипы и обобщенные конструкторы
8.3. Автономные обобщенные конструкторы
8.4. Абстрактные базовые прототипы
8.5. Идиома фреймовых прототипов
8.6. Условные обозначения
8.7. Прототипы и администрирование программ
Упражнения
Простой анализатор с прототипом
Фреймовые прототипы
Литература

Глава 9. Эмуляция символических языков на C++

9.1. Инкрементное программирование на C++
Инкрементный подход и объектно-ориентированное проектирование
Сокращение затрат на компиляцию
Сокращение затрат на компоновку и загрузку
Ускоренные итерации
9.2. Символическая каноническая форма
Класс Top
Класс Thing
Символическая каноническая форма для классов приложений
9.3. Пример обобщенного класса коллекции
9.4. Код и идиомы поддержки инкрементной загрузки
Загрузка виртуальных функций
Обновление структуры класса и функция cutover
Инкрементная загрузка и автономные обобщенные конструкторы
9.5. Уборка мусора
Пример иерархии геометрических фигур с уборкой мусора
9.6. Инкапсуляция примитивных типов
9.7. Мультиметоды в символической идиоме
Упражнения
Литература

Глава 10. Динамическое множественное наследование

10.1. Пример оконной системы с выбором технологии
10.2. Предостережение

Глава 11. Системные аспекты

11.1. Статическая системная структура
Транзакционные диаграммы
Модули
Подсистемы
Каркасы
Библиотеки
11.2. Динамическая системная структура
Планирование
Контексты
Взаимодействие между пространствами имен
Обработка исключений
Зомби
Литература

Приложение А. C в среде C++

А.1. Вызовы функций
А.2. Параметры функций
А.3. Прототипы функций
А.4. Передача параметров по ссылке
А.5. Переменное количество параметров
А.6. Указатели на функции
А.7. Модификатор const
Пример 1. Использование модификатора const вместо директивы #define
Пример 2. Модификатор const и указатели
Пример 3. Объявление функций с константными аргументами
А.8. Взаимодействие с кодом C
А.8.1. Архитектурные аспекты
А.8.2. Языковая компоновка
А.8.3. Вызов функций C++ из C
А.8.4. Совместное использование заголовочных файлов в C и C++
А.8.5. Импорт форматов данных C в C++
А.8.6. Импорт форматов данных С++ в С
Упражнения
Литература

Приложение Б. Программа Shapes

Приложение В. Ссылочные возвращаемые значения операторов

Приложение Г. Поразрядное копирование

Приложение Д. Иерархия геометрических фигур в символической идиоме

Приложение Е. Блочно-структурное программирование на C++

E.1. Концепция блочно-структурного программирования
Е.2. Основные строительные блоки структурного программирования на C++
Е.3. Альтернативное решение с глубоким вложением областей видимости
E.4. Проблемы реализации
Упражнения
Код блочно-структурной видеоигры
Литература

Приложение Ж. Список терминов

Алфавитный указатель

Комментарии

В. Лаптев

Эту книгу надо было перевести еще до того, как она появилась в английском варианте! - это, конечно, шутка, но правды в ней значительно больше, чем шутки. Джефф Элджер сравнил изучение С++ с подъемом на лифте, а мне приходит сравнение с мостом. Программист, изучивший конструкции С++ и принципы объектно-ориентированного программирования, но никогда не создававший реальных программ, стоит на одном берегу реки. Это - берег начального знания. Другой берег - это берег истинного знания, глубокого знания и С++, и программирования вообще. Программист обычно, на свой страх и риск, пускается в плавание по реке, надеясь быстро достичь противоположного берега.

Однако на реке есть мост. Этот мост "построили" Эрих Гамма и Джон Влиссидес, Скотт Мейерс и Джеф Элджер, Николай Джосаттис и Дэвид Вандевурд, Андрей Александреску и Герб Саттер, Стенли Липпман и Эндрю Кениг и, конечно, сам Бъярн Страуструп. Но этот мост не был достроен, в нем не хватало самого первого пролета от берега начального знания. Эта книга - как раз тот самый недостающий начальный пролет "моста".

Это, конечно, излишне эмоциональное отступление, но именно такую реакцию вызвало у меня прочтение этой книги.

Начнем с того, что русское называние не соответствует действительности - в английском варианте название гораздо более точно отражает содержание: "Advanced C++. Programming Styles and Idioms". Джеймс Коплиен (James Coplien) написал ее еще в 1992 году (значительно раньше, чем появилась знаменитая книга "Банды четырех"), и эта именно та книга, которой так не хватало российским программистам и мне в частности.

Во второй главе при постоянном сравнении со структурами С описываются базовые понятия класса и его составляющих. В частности, описываются статические поля и статические методы, константность, в том числе логическая и физическая. На очень простом примере разъясняется понятие указателя на элемент (поле или метод) класса. Даны элементарные правила организации программного кода со "стражами" включения.

Третья глава - очень важная по информационной наполненности. Во-первых, автор вводит "каноническую" форму класса и описывает перегрузку операций, объясняя, между прочим, что такое l-value. Во-вторых, в ней начинаются более серьезные вещи - подсчет ссылок на классическом примере строк. Причем он описывает три решения, а заодно объясняет идиому "манипулятор/тело", которая у Герба Саттера называется "Pimpl", и которая является основой паттерна Bridge (Мост). Здесь же есть пример, как ввести подсчет ссылок для классов, которые изначально не были для этого спроектированы. Когда я прочитал эту главу, у меня возникло стойкое убеждение, что остальные авторы списывали у Коплиена - настолько просто и понятно он написал. Не знаю, может быть, сам он списывал у Страуструпа, но читать Коплиена на множество порядков легче.

Четвертая глава целиком посвящена вопросам, связанным с простым наследованием, но без виртуальных функций - это в пятой главе. На 25 страницах более информативно сказать о наследовании, разъяснив, между прочим, и открытое, и закрытое, и принцип подстановки, наверное невозможно. В конце главы разработан пример иерархии классов с селектором типа. Коплиен, в отличии от Страуструпа, который аналогичный пример приводит как пример отрицательный, собирается использовать его для объяснения механизма виртуальных функций и в нетривиальных идиомах.

В пятой главе объясняется механизм виртуальных функций. Глава большая и, пожалуй, центральная во всей книге - она как раз "по центру" и стоит. Здесь виртуальность объясняется со всех сторон: от простых виртуальных функций, к виртуальным деструкторам, чисто виртуальным функциям и абстрактным классам. Но этим содержание главы не исчерпывается- далее Коплиен немного меняет "угол зрения" на идиому "манипулятор/тело", и объясняет идиому "конверт/письмо", а также рассматривает делегирование, виртуальные конструкторы (причем два разных подхода), итераторы и курсоры. В этой же главе определяются функторы (в 92 году!) и описывается парадигма аппликативного и функционального программирования на С++! А есть еще множественное наследование и виртуальные базовые классы.

И опять хочется сказать несколько "теплых" слов нашим издательствам: где ж вы были раньше, почему я держу эту книгу в руках только сейчас, а не 10 лет назад, когда она действительно была нужна мне позарез! Формулировки настолько простые и точные, что виртуальные функции, которые обычно у новичка вызывают массу вопросов, кажутся "проще пареной репы". Например: "Стиль программирования, в котором этот механизм (виртуальных функций) логически последовательно применяется к конкретным типам данных, называется объектно-ориентированным программированием; эта методика является наиболее прямолинейным способом поддержки объектно-ориентированного проектирования в С++". И ни в одной книге вы не найдете такого точного и абсолютно ясного определения делегирования: "динамическая имитация наследования на стадии выполнения:". Я, конечно, и раньше встречал разные описания делегирования, но только Коплиен сказал: "Делегирование" открывает перед экземплярами объектов те же возможности, что и наследование перед классами - то есть возможности совместного использования кода и автоматического применения кода одной абстракции для обработки запросов, обращенных к другой абстракции".

Далее в книге разбираются более общие вопросы, связанные с проектированием и повторным использованием кода, которые, однако сопровождаются многочисленными примерами на С++ и иллюстрациями на UML (в той старой версии Гради Буча). Глава о прототипах - это блестящее объяснение паттерна "Фабрика объектов" в различных вариантах.

Глава 9 хоть и называется "Эмуляция символических языков на С++", однако по словам самого Коплиена "приемы, описанные в этой главе, не должны рассматриваться как замена для SmallTalk или объектно-ориентированных сред программирования на базе Lisp. Представленные идиомы помогут вместе с С++ пройти несколько шагов в указанном направлении:". В этой главе, например, приводится пример обобщенного класса коллекции (Элджер, наверное, списывал это и некоторые другие вещи, у Коплиена ;). Здесь же есть и основы сборки мусора, и мультиметоды.

Главу 10 и 11 мне еще самому нужно освоить, но думаю, для многих программистов в них содержится немало интересной и полезной информации.

Что еще понравилось. В каждой главе есть небольшой набор упражнений, в которых можно встретить отнюдь не тривиальные вопросы, например: может ли конструктор определить, вызван ли он в результате выполнения оператора new или же для объекта, для которого уже была выделена память? Почему?

В книге много полезных приложений, в том числе и к отдельным главам. Кстати, приложение Ж можно взять за основу словаря терминов для RSDN.

В общем, книга совершенно не производит впечатление устаревшей, однозначно "must have" практически для всех программистов.