- •1. Понятие класса. Методы класса. Управление доступом к компонентам.
- •2. Объявление и определение класса. Внешнее определение функций.
- •3. Создание, копирование и удаление объекта.
- •4. Статические компоненты класса. Инициализация статических компонентов класса.
- •5. Наследование. Типы наследования. Виртуальное наследование.
- •6. Виртуальные функции
- •7. Абстрактные классы и чистые виртуальные функции. Интерфейс
- •8. Дружественность. Дружественные классы и функции.
- •10. Шаблоны классов
- •9. Вложенные классы. Внутреннее и внешнее определение.
- •11.Создание экземпляров шаблона. Инстанцирование.
- •12.Шаблоны и наследование.
- •13.Терминология шаблонов.
- •14. Параметры и аргументы шаблона.
- •15. Шаблоны компонентных функций
- •16. Полная специализация шаблонов.
- •17. Частичная специализация шаблонов.
- •18. Перегрузка операций. Основные понятия.
- •19. Перегрузка унарных операций.
- •20. Перегрузка бинарных операций.
- •Int test() {
- •Int test() {
- •Int test() {
- •// Делаем что-то
- •Вопрос 23
- •24. Группировка и композиция исключений. Повторная генерация. Перехват всех исключений.
- •25. Автоматическое управление ресурсами. Методика raii.
- •Void f() { FileOpen("myfile.Txt", "rt"); //здесь выполняем нужную работу с файлом //... }
- •Void f (int a) throw (x2, x3)
- •27. Стандартная библиотека. Организация стандартной библиотеки
- •28. Тип вектора. Вложенные типы. Итераторы. Доступ к элементам
- •29.Тип Вектора. Конструкторы. Операции со стеком. Списочные операции. Размеры и емкость.
- •30. Стандартные контейнеры. Вопросы производительности операций.
- •31. Процесс разработки по. Цели и этапы проектирования.
- •32. Процесс разработки по. Выявление классов. Определение операций.
- •33. Процесс разработки по. Определение взаимосвязей. Определение интерфейсов.
- •Этап 3: выявление зависимостей
- •Этап 4: определение интерфейсов
- •34. Паттерны проектирования. Основные паттерны.
- •35. Тестирование по. Методы тестирования.
33. Процесс разработки по. Определение взаимосвязей. Определение интерфейсов.
Этап 3: выявление зависимостей
Уточните классы в плане их зависимостей. Различные виды зависимостей обсуждаются в §24.3. В контексте проектирования ключевыми являются зависимости параметризация, наследования и использования. Для каждой из них важно ответить на вопрос о том, что означает, что класс ответственен за какое-то одно из свойств системы. Чтобы классу быть ответственным за что-то, ему не обязательно самому содержать все необходимые для этого данные, или непосредственно выполнять все требуемые операции. Более того, классы с фиксированной ответственностью за отдельные свойства системы чаще всего переправляют идущие на них запросы другим классам, которые отвечают за решение частных подзадач. Естественно, тут можно переборщить и создать чрезвычайно неэффективную и труднопонимаемую архитектуру, в рамках которой никакая работа не делается иначе, как порождением каскада обращений объектов за сервисом друг к другу. То, что можно сделать на месте, должно делаться сразу на этом месте.
Необходимость рассмотрения вопросов наследования и отношений использования на этапе проектирования (а не реализации) вытекает из перехода от простого использования классов к представлению концепций задачи. Отсюда следует, что единицей проекта является компонент (§23.4.3, §24.4), а не индивидуальный класс.
Параметризация — часто приводящая к применения шаблонов — это способ явного представления неявных зависимостей, позволяющая представить альтернативы без введения новых концепций. Часто имеется возможность выбора между тем, чтобы оставить что-то зависеть от контекста, или представить в виде ветви дерева наследования, или воспользоваться параметром (§24.4.1).
Этап 4: определение интерфейсов
Определите интерфейсы. Закрытые (private,) функции обычно не рассматриваются на этапе проектирования. Вопросы реализации на этапе проектирования по большей части связаны с зависимостями, возникшими на этапе 3. Кроме того, я вывел эмпирическое правило, гласящее: «если для класса не возможны по крайней мере две реализации, то с этим классом что-то не так». Это, скорее всего, не представление концепции, а замаскированная определенная реализация. Во многих случаях, рассмотрение возможности медленной эволюции класса есть приближение к ответу на вопрос «достаточно ли независим интерфейс класса от реализации?».
Открытые базовые классы, а также друзья класса являются частью интерфейса; см. также §11.5 и §24.4.2. Обеспечение раздельных интерфейсов для наследования и для обычных клиентов путем предоставления защищенных и открытых интерфейсов является упражнением, заслуживающим поощрения.
На данном шаге выявляются и специфицируются точные типы аргументов. В идеале нужно стремиться к тому, чтобы максимально полно статически типизировать интерфейсы в рамках типов прикладной задачи; см. §24.2.3 и §24.4.2.
В процессе определения интерфейсов выявляйте классы, чьи операции, как кажется, поддерживают несколько уровней абстракции. Например, некоторые функции-члены класса File могут принимать аргументы типа File descriptor, в то время как другие — строковые описания имен файлов. Операции, принимающие File descriptor, и операции, принимающие имена файлов, работают на разных уровнях абстракции, так что может возникнуть вопрос, относятся ли они к одному и тому же классу. Может лучше организовать два класса, каждый из которых поддерживает либо файловый дескриптор, либо имена файлов. В типичном случае, все операции класса должны поддерживать одинаковый уровень абстракции. Если это не так, то стоит подумать о реорганизации этого класса и родственных ему классов.
