- •Глава 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 Управление памятью
1.5 Поддержка объектно-ориентированного программирования
Поддержку объектно-ориентированного программирования обеспечивают
классы вместе с механизмом наследования, а также механизм вызова
функций-членов в зависимости от истинного типа объекта (дело в том, что
возможны случаи, когда этот тип неизвестен на стадии трансляции). Особенно
важную роль играет механизм вызова функций-членов. Не менее важны
средства, поддерживающие абстракцию данных (о них мы говорили ранее). Все
доводы в пользу абстракции данных и базирующихся на ней методов, которые
позволяют естественно и красиво работать с типами, действуют и для языка,
поддерживающего объектно-ориентированное программирование. Успех обоих
методов зависит от способа построения типов, от того, насколько они
просты, гибки и эффективны. Метод объектно-ориентированного
программирования позволяет определять более общие и гибкие
пользовательские типы по сравнению с теми, которые получаются, если
использовать только абстракцию данных.
1.5.1 Механизм вызова
Основное средство поддержки объектно-ориентированного программирования
- это механизм вызова функции-члена для данного объекта, когда истинный
тип его на стадии трансляции неизвестен. Пусть, например, есть указатель
p. Как происходит вызов p->rotate(45)? Поскольку С++ базируется на
статическом контроле типов, задающее вызов выражение имеет смысл только
при условии, что функция rotate() уже была описана. Далее, из обозначения
p->rotate() мы видим, что p является указателем на объект некоторого
класса, а rotate должна быть членом этого класса. Как и при всяком
статическом контроле типов проверка корректности вызова нужна для того,
чтобы убедиться (насколько это возможно на стадии трансляции), что типы в
программе используются непротиворечивым образом. Тем самым гарантируется,
что программа свободна от многих видов ошибок.
Итак, транслятору должно быть известно описание класса, аналогичное
тем, что приводились в $$1.2.5:
class shape
{
// ...
public:
// ...
virtual void rotate ( int );
// ...
};
а указатель p должен быть описан, например, так:
T * p;
где T - класс shape или производный от него класс. Тогда транслятор
видит, что класс объекта, на который настроен указатель p, действительно
имеет функцию rotate(), а функция имеет параметр типа int. Значит,
p->rotate(45) корректное выражение.
Поскольку shape::rotate() была описана как виртуальная функция, нужно
использовать механизм вызова виртуальной функции. Чтобы узнать, какую
именно из функций rotate следует вызвать, нужно до вызова получить из
объекта некоторую служебную информацию, которая была помещена туда при его
создании. Как только установлено, какую функцию надо вызвать, допустим
circle::rotate, происходит ее вызов с уже упоминавшимся контролем типа.
Обычно в качестве служебной информации используется таблица адресов
функций, а транслятор преобразует имя rotate в индекс этой таблицы. С
учетом этой таблицы объект типа shape можно представить так:
center
vtbl:
color &X::draw
&Y::rotate
...
...
Функции из таблицы виртуальных функций vtbl позволяют правильно
работать с объектом даже в тех случаях, когда в вызывающей функции
неизвестны ни таблица vtbl, ни расположение данных в части объекта,
обозначенной ... . Здесь как X и Y обозначены имена классов, в которые
входят вызываемые функции. Для объекта circle оба имени X и Y есть circle.
Вызов виртуальной функции может быть по сути столь же эффективен, как
вызов обычной функции.
