- •Глава 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.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 Управление памятью
Vertical_scrollbar или с помощью одного типа scrollbar, который
имеет аргумент, определяющий, является расположение вертикальным
или горизонтальным. Первое решение предполагает, что есть еще
третий тип, задающий просто свиток - scrollbar, и этот тип
является базовым классом для двух определенных свитков. Второе
решение предполагает дополнительный аргумент у типа scrollbar и
наличие значений, задающих вид свитка. Например, так:
enum orientation { horizontal, vertical };
Как только мы остановимся на одном из решений, определится
объем изменений, которые придется внести в систему. Допустим, в
этом примере нам потребуется ввести свитки третьего вида. Вначале
предполагалось, что могут быть свитки только двух видов (ведь
всякое окно имеет только два измерения), но в этом примере,
как и во многих других, возможны расширения, которые возникают
как вопросы перепроектирования. Например, может появиться
желание использовать "управляющую кнопку" (типа мыши) вместо свитков
двух видов. Такая кнопка задавала бы прокрутку в различных
направлениях в зависимости от того, в какой части окна нажал
ее пользователь. Нажатие в середине верхней строчки должно
вызывать "прокручивание вверх", нажатие в середине левого столбца -
"прокручивание влево", нажатие в левом верхнем углу -
"прокручивание вверх и влево". Такая кнопка не является
чем-то необычным, и ее можно рассматривать как уточнение понятия
свитка, которое особенно подходит для тех областей приложения,
которые связаны не с обычными текстами, а с более сложной
информацией.
Для добавления управляющей кнопки к программе, использующей
иерархию из трех свитков, требуется добавить еще один класс, но
не нужно менять программу, работающую со старыми свитками:
свиток
горизонтальный_свиток вертикальный_свиток управляющая_кнопка
Это положительная сторона "иерархического решения".
Задание ориентации свитка в качестве параметра приводит к
заданию полей типа в объектах свитка и использованию переключателей
в теле функций-членов свитка. Иными словами, перед нами обычная
дилемма: выразить данный аспект структуры системы с помощью
определений или реализовать его в операторной части программы.
Первое решение увеличивает объем статических проверок и объем
информации, над которой могут работать разные вспомогательные
средства. Второе решение откладывает проверки на стадию выполнения
и разрешает менять тела отдельных функций, не изменяя общую
структуру системы, какой она представляется с точки зрения
статического контроля или вспомогательных средств. В большинстве
случаев, предпочтительнее первое решение.
Положительной стороной решения с единым типом свитка является то,
что легко передавать информацию о виде нужного нам свитка другой
функции:
void helper(orientation oo)
{
//...
p = new scrollbar(oo);
//...
}
void me()
{
helper(horizontal);
}
Такой подход позволяет на стадии выполнения легко перенастроить свиток
на другую ориентацию. Вряд ли это очень важно в примере со свитками,
но это может оказаться существенным в похожих примерах. Суть в том,
что всегда надо делать определенный выбор, а это часто непросто.
Теперь рассмотрим как привязать свиток к окну. Если считать
window_with_scrollbar (окно_со_свитком) как нечто, что является
window и scrollbar, мы получим подобное:
class window_with_scrollbar
: public window, public scrollbar {
// ...
};
Это позволяет любому объекту типа window_with_scrollbar выступать
и как window, и как scrollbar, но от нас требуется решение
использовать только единственный тип scrollbar.
Если, с другой стороны, считать window_with_scrollbar объектом
типа window, который имеет scrollbar, мы получим такое определение:
class window_with_scrollbar : public window {
// ...
scrollbar* sb;
public:
window_with_scrollbar(scrollbar* p, /* ... */)
: window(/* ... */), sb(p)
{
// ...
}
// ...
};
Здесь мы можем использовать решение со свитками трех типов. Передача
самого свитка в качестве параметра позволяет окну (window) не
запоминать тип его свитка. Если потребуется, чтобы объект типа
window_with_scrollbar действовал как scrollbar, можно добавить
операцию преобразования:
window_with_scrollbar :: operator scrollbar&()
{
return *sb;
}
