- •0. Введение: о курсе: версия для печати и pda
- •1.2 Парадигмы программирования
- •1.2.1 Процедурное программирование
- •1.2.5 Объектно-ориентированное программирование
- •1.5.1 Механизм вызова
- •1.5.3 Множественное наследование
- •1.6 Пределы совершенства
- •2. Лекция: Описания и константы: версия для печати и pda
- •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.3.1 Единственный заголовочный файл
- •4.3.2 Множественные заголовочные файлы
- •4.4 Связывание с программами на других языках
- •5.3.1 Альтернативные реализации
- •5.3.2 Законченный пример класса
- •5.5.3 Свободная память
- •5.5.5 Массивы объектов класса
- •6. Лекция: Производные классы: версия для печати и pda
- •6.1 Введение и краткий обзор
- •6.2.3 Иерархия классов
- •6.2.4 Поля типа
- •6.4.1 Монитор экрана
- •6.5 Множественное наследование
- •7.3 Пользовательские операции преобразования типа
- •7.3.2 Операции преобразования
- •7.3.3 Неоднозначности
- •7.5 Большие объекты
- •Int size; // размер вектора, на который указывает p
- •7.13 Предостережения
- •7.14 Упражнения
- •8. Лекция: Шаблоны типа: версия для печати и pda
- •8.1 Введение
- •8.3.2 Список без принудительной связи
- •8.4.4 Неявная передача операций
- •8.4.5 Введение операций с помощью параметров шаблонного класса
- •8.7.1 Задание реализации с помощью параметров шаблона
- •9.1.2 Другие точки зрения на особые ситуации
- •9.3.2 Производные особые ситуации
- •9.4.2 Предостережения
- •9.4.3 Исчерпание ресурса
- •9.9 Упражнения
- •10.1 Введение
- •10.2 Вывод
- •10.2.1 Вывод встроенных типов
- •10.4.1.2 Поля вывода
- •10.4.1.4 Вывод целых
- •10.5.1 Закрытие потоков
- •10.5.2 Строковые потоки
- •X Целый параметр выдается в шестнадцатеричной записи;
- •11. Лекция: Проектирование и развитие: версия для печати и pda
- •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.1 Игнорирование классов
- •12.1.2 Игнорирование наследования
- •12.1.3 Игнорирование статического контроля типов
- •12.1.4 Гибридный проект
- •12.2 Классы
- •12.2.1 Что представляют классы?
- •12.2.2 Иерархии классов
- •12.2.3 Зависимости в рамках иерархии классов.
- •12.2.7 Отношения внутри класса
- •12.3 Компоненты
- •12.4 Интерфейсы и реализации
- •12.5 Свод правил
- •13. Лекция: Проектирование библиотек: версия для печати и pda
- •13.1 Введение
- •13.2 Конкретные типы
- •13.5.1 Информация о типе
- •13.6 Обширный интерфейс
- •13.7 Каркас области приложения
- •13.8 Интерфейсные классы
- •13.10 Управление памятью
12.2 Классы
Основное положение объектно-ориентированного проектирования и программирования заключается в том, что программа служит моделью некоторых понятий реальности. Классы в программе представляют основные понятия области приложения и, в частности, основные понятия самого процесса моделирования реальности. Объекты классов представляют предметы реального мира и продукты процесса реализации.
Мы рассмотрим структуру программы с точки зрения следующих взаимоотношений между классами:
отношения наследования,
отношения принадлежности,
отношения использования и
запрограммированные отношения.
При рассмотрении этих отношений неявно предполагается, что их анализ является узловым моментом в проекте системы. В §12.4 исследуются свойства, которые делают класс и его интерфейс полезными для представления понятий. Вообще говоря, в идеале, зависимость класса от остального мира должна быть минимальна и четко определена, а сам класс должен через интерфейс открывать лишь минимальный объем информации для остального мира.
Подчеркнем, что класс в С++ является типом, поэтому сами классы и взаимоотношения между ними обеспечены значительной поддержкой со стороны транслятора и в общем случае поддаются статическому анализу.
12.2.1 Что представляют классы?
По сути в системе бывают классы двух видов:
классы, которые прямо отражают понятия области приложения, т.е. понятия, которые использует конечный пользователь для описания своих задач и возможных решений; и
классы, которые являются продуктом самой реализации, т.е. отражают понятия, используемые разработчиками и программистами для описания способов реализации.
Некоторые из классов, являющихся продуктами реализации, могут представлять и понятия реального мира. Например, программные и аппаратные ресурсы системы являются хорошими кандидатами на роль классов, представляющих область приложения. Это отражает тот факт, что систему можно рассматривать с нескольких точек зрения, и то, что с одной является деталью реализации, с другой может быть понятием области приложения. Хорошо спроектированная система должна содержать классы, которые дают возможность рассматривать систему с логически разных точек зрения. Приведем пример:
классы, представляющие пользовательские понятия (например, легковые машины и грузовики),
классы, представляющие обобщения пользовательских понятий (движущиеся средства),
классы, представляющие аппаратные ресурсы (например, класс управления памятью),
классы, представляющие системные ресурсы (например, выходные потоки),
классы, используемые для реализации других классов (например, списки, очереди, блокировщики) и
встроенные типы данных и структуры управления.
В больших системах очень трудно сохранять логическое разделение типов различных классов и поддерживать такое разделение между различными уровнями абстракции. В приведенном выше перечислении представлены три уровня абстракции:
[1+2] представляет пользовательское отражение системы,
[3+4] представляет машину, на которой будет работать система,
[5+6] представляет низкоуровневое (со стороны языка программирования) отражение реализации.
Чем больше система, тем большее число уровней абстракции необходимо для ее описания, и тем труднее определять и поддерживать эти уровни абстракции. Отметим, что таким уровням абстракции есть прямое соответствие в природе и в различных построениях человеческого интеллекта. Например, можно рассматривать дом как объект, состоящий из
атомов,
молекул,
досок и кирпичей,
полов, потолков и стен;
комнат.
Пока удается хранить раздельно представления этих уровней абстракции, можно поддерживать целостное представление о доме. Однако, если смешать их, возникнет бессмыслица. Например, предложение "Мой дом состоит из нескольких тысяч фунтов углерода, некоторых сложных полимеров, из 5000 кирпичей, двух ванных комнат и 13 потолков" - явно абсурдно. Из-за абстрактной природы программ подобное утверждение о какой-либо сложной программной системе далеко не всегда воспринимают как бессмыслицу.
В процессе проектирования выделение понятий из области приложения в класс вовсе не является простой механической операцией. Обычно эта задача требует большой проницательности. Заметим, что сами понятия области приложения являются абстракциями. Например, в природе не существуют "налогоплательщики", "монахи" или "сотрудники".
Эти понятия не что иное, как метки, которыми обозначают бедную личность, чтобы классифицировать ее по отношению к некоторой системе. Часто реальный или воображаемый мир (например, литература, особенно фантастика) служат источником понятий, которые кардинально преобразуются при переводе их в классы. Так, экран моего компьютера (Маккинтош) совсем не походит на поверхность моего стола, хотя компьютер создавался с целью реализовать понятие "настольный", а окна на моем дисплее имеют самое отдаленное отношение к приспособлениям для презентации чертежей в моей комнате. Я бы не вынес такого беспорядка у себя на экране.
Суть моделирования реальности не в покорном следовании тому, что мы видим, а в использовании реальности как начала для проектирования, источника вдохновения и как якоря, который удерживает, когда стихия программирования грозит лишить нас способности понимания своей собственной программы.
Здесь полезно предостеречь: новичкам обычно трудно "находить" классы, но вскоре это преодолевается без каких-либо неприятностей. Далее обычно приходит этап, когда классы и отношения наследования между ними бесконтрольно множатся. Здесь уже возникают проблемы, связанные со сложностью, эффективностью и ясностью полученной программы. Далеко не каждую отдельную деталь следует представлять отдельным классом, и далеко не каждое отношение между классами следует представлять как отношение наследования. Старайтесь не забывать, что цель проекта - смоделировать систему с подходящим уровнем детализации и подходящим уровнем абстракции. Для больших систем найти компромисс между простотой и общностью далеко не простая задача.
