
- •Глава 6 посвящена понятию производных классов, которое позволяет строить
- •Раздел 3.4 главы 2. Для обозначения справочного руководства применяется
- •1991 Г.Г. (такие как множественное наследование, статические функции-члены
- •1.1 Введение
- •1.2 Парадигмы программирования
- •1.2.1 Процедурное программирование
- •1.2.5 Объектно-ориентированное программирование
- •1.5 Поддержка объектно-ориентированного программирования
- •1.5.1 Механизм вызова
- •1.5.2 Проверка типа
- •1.5.3 Множественное наследование
- •1.6 Пределы совершенства
- •2.2 Имена
- •2.3.2 Неявное преобразование типа
- •2.4 Литералы
- •2.4.4 Строки
- •2.6. Экономия памяти
- •2.6.1 Поля
- •3.1.1 Анализатор
- •3.1.2 Функция ввода
- •3.2 Сводка операций
- •3.2.3 Инкремент и декремент
- •3.2.5 Преобразование типа
- •3.2.6 Свободная память
- •3.3.2 Оператор goto
- •4.1 Введение
- •4.3.1 Единственный заголовочный файл
- •4.3.2 Множественные заголовочные файлы
- •4.4 Связывание с программами на других языках
- •4.6.3 Передача параметров
- •5.1 Введение и краткий обзор
- •5.3.1 Альтернативные реализации
- •5.3.2 Законченный пример класса
- •Vector и matrix, мы могли бы обойтись без контроля индекса при
- •5.4.5 Указатели на члены
- •5.4.6 Структуры и объединения
- •5.5.3 Свободная память
- •5.5.5 Массивы объектов класса
- •6.1 Введение и краткий обзор
- •6.2.3 Иерархия классов
- •6.2.4 Поля типа
- •6.2.5 Виртуальные функции
- •6.4.1 Монитор экрана
- •6.5 Множественное наследование
- •7.1 Введение
- •7.3 Пользовательские операции преобразования типа
- •7.3.2 Операции преобразования
- •7.3.3 Неоднозначности
- •7.5 Большие объекты
- •Void f2(t a) // вариант с контролем
- •Void f3(t a) // вариант с контролем
- •Inv() обращает саму матрицу m, а не возвращает новую, обратную m,
- •7.13 Предостережения
- •8.1 Введение
- •8.4.4 Неявная передача операций
- •8.4.5 Введение операций с помощью параметров шаблонного класса
- •8.7.1 Задание реализации с помощью параметров шаблона
- •9.1 Обработка ошибок
- •9.1.2 Другие точки зрения на особые ситуации
- •9.3.2 Производные особые ситуации
- •9.4.2 Предостережения
- •9.4.3 Исчерпание ресурса
- •9.4.4 Особые ситуации и конструкторы
- •9.5 Особые ситуации могут не быть ошибками
- •10.1 Введение
- •10.2 Вывод
- •10.2.1 Вывод встроенных типов
- •10.4.1.2 Поля вывода
- •10.4.1.4 Вывод целых
- •Istream - шаблон типа smanip, а smanip - двойник для ioss.
- •10.5.1 Закрытие потоков
- •10.5.2 Строковые потоки
- •X Целый параметр выдается в шестнадцатеричной записи;
- •11.1 Введение
- •11.2 Цели и средства
- •11.3 Процесс развития
- •11.3.1 Цикл развития
- •11.3.2 Цели проектирования
- •11.3.3 Шаги проектирования
- •11.3.3.1 Шаг 1: определение классов
- •11.3.3.2 Шаг 2: определение набора операций
- •11.3.3.3 Шаг 3: указание зависимостей
- •11.3.3.4 Шаг 4: определение интерфейсов
- •11.3.3.5 Перестройка иерархии классов
- •11.3.3.6 Использование моделей
- •11.3.4 Эксперимент и анализ
- •11.3.5 Тестирование
- •11.3.6 Сопровождение
- •11.3.7 Эффективность
- •11.4 Управление проектом
- •11.4.1 Повторное использование
- •11.4.2 Размер
- •11.4.3 Человеческий фактор
- •11.5 Свод правил
- •11.6 Список литературы с комментариями
- •12.1 Проектирование и язык программирования.
- •12.1.1 Игнорирование классов
- •12.1.2 Игнорирование наследования
- •12.1.3 Игнорирование статического контроля типов
- •12.1.4 Гибридный проект
- •12.2 Классы
- •12.2.1 Что представляют классы?
- •12.2.2 Иерархии классов
- •12.2.3 Зависимости в рамках иерархии классов.
- •Vertical_scrollbar или с помощью одного типа scrollbar, который
- •12.2.6 Отношения использования
- •12.2.7 Отношения внутри класса
- •12.3 Компоненты
- •12.4 Интерфейсы и реализации
- •12.5 Свод правил
- •13.1 Введение
- •13.2 Конкретные типы
- •13.4 Узловые классы
- •1, 2, 6 И 7. Класс, который не удовлетворяет условию 6, походит
- •13.5.1 Информация о типе
- •13.6 Обширный интерфейс
- •13.7 Каркас области приложения
- •13.8 Интерфейсные классы
- •13.10 Управление памятью
12.1.1 Игнорирование классов
Рассмотрим первый из указанных моментов - игнорирование классов.
В таком случае получившаяся программа на С++ будет приблизительно
эквивалентна С-программе, разработанной по тому же проекту, и,
можно сказать, что они будут приблизительно эквивалентны программам
на Аде или Коболе, разработанным по нему же.
По сути проект составлен как независящий от языка реализации, что
принуждает программиста ограничиваться общим подмножеством языков
С, Ада или Кобол. Здесь есть свои преимущества. Например, получившееся
в результате строгое разделение данных и программного кода позволяет
легко использовать традиционные базы данных, которые разработаны
для таких программ. Поскольку используется ограниченный язык
программирования, от программистов требуется меньше опытности
(или, по крайней мере другой ее уровень). Для многих приложений,
например, для традиционных баз данных, работающих с
файлом последовательно, такой подход вполне разумен, а традиционные
приемы, отработанные за десятилетия, вполне адекватны задаче.
Однако там, где область приложения существенно отличается от
традиционной последовательной обработки записей (или символов),
или сложность задачи выше, как, например, в диалоговой системе
CASE, недостаток языковой поддержки абстрактных данных
из-за отказа от классов (если их не учитывать) повредит
проекту. Сложность задачи не уменьшится, но, поскольку система
реализована на обедненном языке, структура программы плохо будет
отвечать проекту. У нее слишком большой объем, не хватает проверки типов,
и, вообще, она плохо приспособлена для использования различных
вспомогательных средств. Это путь, приводящий к кошмарам при ее
сопровождении.
Обычно для преодоления указанных трудностей создают специальные
средства, поддерживающие понятия, используемые в проекте. Благодаря
им создаются конструкции более высокого
уровня и организуются проверки с целью компенсировать дефекты
(или сознательное обеднение) языка реализации. Так метод
проектирования становится самоцелью, и для него создается специальный
язык программирования. Такие языки программирования в большинстве
случаев являются плохой заменой широко распространенных языков
программирования общего назначения, которые сопровождаются
подходящими средствами проектирования. Использовать С++ с таким
ограничением, которое должно компенсироваться при проектировании
специальными средствами, бессмысленно. Хотя несоответствие между
языком программирования и средствами проектирования может быть просто
стадией процесса перехода, а значит временным явлением.
Самой типичной причиной игнорирования классов при проектировании
является простая инерция. Традиционные языки программирования не
предоставляют понятия класса, и в традиционных методах проектирования
отражаются этот недостаток. Обычно в процессе проектирования
наибольшее внимание уделяется разбиению задачи на процедуры,
производящие требуемые действия. В главе 1 это понятие называлось
процедурным программированием, а в области проектирования оно
именуется как функциональная декомпозиция. Возникает типичный
вопрос "Можно ли использовать С++ совместно с методом проектирования,
базирующимся на функциональной декомпозиции?" Да, можно, но,
вероятнее всего, в результате вы придете к использованию С++ как
просто улучшенного С со всеми указанными выше проблемами. Это
может быть приемлемо на период перехода на новый язык, или для
уже завершенного проектирования, или для подзадач, в которых
использование классов не дает существенных выгод (если учитывать
опыт программирования на С++ к данному моменту), но в общем
случае на большом отрезке времени отказ от свободного
использования классов, связанный с методом функциональной
декомпозиции, никак не совместим с эффективным использованием С++.
Процедурно-ориентированный и объектно-ориентированный
подходы к программированию различаются по своей сути и обычно
ведут к совершенно разным решениям одной задачи. Этот вывод
верен как для стадии реализации, так и для стадии проектирования:
вы концентрируете внимание или на предпринимаемых действиях, или на
представляемых сущностях, но не на том и другом одновременно.
Тогда почему метод объектно-ориентированного проектирования
предпочтительнее метода функциональной декомпозиции?
Главная причина в том, что функциональная декомпозиция не дает
достаточной абстракции данных. А отсюда уже следует, что проект
будет
- менее податливым к изменениям,
- менее приспособленным для использования различных вспомогательных
средств,
- менее пригодным для параллельного развития и
- менее пригодным для параллельного выполнения.
Дело в том, что функциональная декомпозиция вынуждает объявлять
"важные" данные глобальными, поскольку, если система структурирована
как дерево функций, всякое данное, доступное двум функциям, должно
быть глобальным по отношению к ним. Это приводит к тому, что
"важные" данные "всплывают" к вершине дерева, по
мере того как все большее число функций требует доступа к нимЬ.
Ь В точности так же происходит в случае иерархии классов с одним
корнем, когда "важные" данные всплывают по направлению к базовому
классу.
Когда мы концентрируем внимание на описаниях классов, заключающих
определенные данные в оболочку, то зависимости между различными
частями программы выражены явно и можно их проследить. Еще более
важно то, что при таком подходе уменьшается число зависимостей
в системе за счет лучшей расстановки ссылок на данные.
Однако, некоторые задачи лучше решаются с помощью набора
процедур. Смысл "объектно-ориентированного" проектирования не в
том, чтобы удалить все глобальные процедуры из программы или
не иметь в системе процедурно-ориентированных частей. Основная
идея скорее в том, что классы, а не глобальные процедуры становятся
главным объектом внимания на стадии проектирования. Использование
процедурного стиля должно быть осознанным решением, а не решением,
принимаемым по умолчанию. Как классы, так и процедуры следует
применять сообразно области приложения, а не просто как
неизменные методы проектирования.