- •Санкт-Петербургский
- •Процедурное программирование
- •Объектно-ориентированное программирование
- •Обобщенное программирование
- •На пути к объектно-ориентированному программированию
- •Абстракция сущностей и процедурный язык программирования
- •Абстрактный тип данных
- •Организация класса
- •Определение и объявление класса
- •Члены класса
- •Маркеры доступа
- •Конструкторы
- •Понятие об объекте
- •Организация кода при работе с классами
- •Статические компоненты класса
- •Дружественные функции и дружественные классы
- •Особенности применения дружественных функций и классов
- •Перегрузка оператров
- •Перегрузка оператора присваивания
- •Реализация перегруженного оператора присваивания для класса Array
- •Перегрузка оператора индексирования
- •Понятие о константной функции
- •Константный вариант перегруженного оператора индексирования
- •Вычисление смешанных выражений
- •Наследование
- •Структура объекта порожденного класса
- •Доступ к элементам базового класса
- •Конструкторы порожденного класса
- •Порядок создания объекта порожденного класса
- •Перегруженный оператор присваивания порожденного класса
- •Вызов виртуальной функции из тела невиртуальной функции
- •Виртуализация функций не-членов класса
- •Идиома невиртуального интерфейса (nvi)
- •Реализация механизма виртуальных функций
- •Накладные расходы при работе с виртуальными функциями
- •Чисто виртуальные функции. Абстрактные базовые классы
- •Виртуальные деструкторы
- •Автономные и базовые классы
- •Дублирование подобъектов
- •Конструкторы при виртуальном наследовании
- •Работа с данными при виртуальном наследовании
- •Обработка исключительных ситуаций
- •Завершение или продолжение
- •Распределение обязанностей между разработчиком и клиентом
- •Генерация исключений
- •Объект исключения
- •Раскрутка стека
- •Спецификации исключений
- •Работа с обработчиками
- •Формат обработчика
- •Пример обработки исключений
- •Современная точка зрения на спецификации исключения
- •Шаблоны функций
- •Объявление и определение шаблона функции
- •Примеры объявлений и определений шаблонов функций
- •Инстанцирование шаблона функции
- •Неявное инстанцирование
- •Явное инстанцирование конкретной функции
- •Структура использования шаблона функции с явным инстанцированием
- •Перегрузка шаблона функции
- •Явная специализация шаблона функции
- •Шаблоны классов
- •Использование шаблона класса
- •Наследование и шаблоны
- •Шаблоны классов и отношение включения
- •Рекурсивное использование шаблонов классов
- •Друзья и шаблоны классов
- •Явная и частичная специализация шаблона класса
- •Алгоритмы
- •Алгоритм for_each
- •Функциональные объекты
- •Алгоритм copy
- •Алгоритм sort
- •Термины и определения
- •.Литература
Структура объекта порожденного класса
Пусть имеются два класса AиB, связанные отношением наследования.
A
int n;
int m;
B
-int
k;
Предположим, что в клиентском коде имеется следующее определение переменной b:
Bb;
Изобразим диаграмму объекта b.
b : B
n =
0 m =
0 k =
0
Объект b,будет содержать три поля с именамиn,mиk. Два из них (nиm) рассматриваемый объект наследует от базового класса, а полеkявляется его собственным полем. На диаграмме показаны значения, которыми были предположительно инициализированы эти поля.
Доступ к элементам базового класса
Доступность элементов базового класса в порожденном классе зависит от вида наследования.
Вид наследования |
Права доступа в базовом классе |
Права доступа в порожденном классе |
public |
private |
private |
protected |
protected | |
public |
public | |
Protected |
private |
private |
protected |
protected | |
public | ||
Private |
private |
private |
protected | ||
Public |
Обсуждение.
В языке C++ для обеспечения сокрытия информации используется принцип управления доступом, а не управление видимостью. Для уяснения различия между этими двумя подходами, рассмотрим следующий пример.
// Файл Сlasses.h class A { private: int n; }; class B : public A { public: void foo(); }; // Файл B.cpp int n; void B :: foo() { int n = 5; // ... }
При компиляции рассматриваемого программного кода будет выведено сообщение об ошибке Дело в том, что в теле функции foo() видна закрытая переменная – член базового класса А. Эта переменная скрывает глобальную переменнуюn, объявленную в файлеB.cpp. Если бы сокрытие информации осуществлялось за счет управления видимостью, то сообщение об ошибке появляться не должно.
Итак, очень важный вывод состоит в том, что все закрытые элементы базового класса в порожденном классе видны, но недоступны. Заметим, что в других объектно-ориентированных языках могут быть приняты свои способы сокрытия информации. Например, в ObjectPascalDelphiэто осуществляется за счет управления видимостью.
Требует осуждения следующий вопрос. Связи с чем функциям порожденного класса не предоставлен доступ к реализации базового класса. На это есть определенные причины. Дело в том, что в противном случае клиент также может сравнительно легко получить такой же доступ. Для этого ему достаточно породить класс.
В разделе protectedследует размещать те элементы базового класса, которые должны быть доступны порожденному классу, но не должны быть доступны его клиентам. Не рекомендуется в этот раздел базового класса включать элементы его реализации.
При public– наследовании открытый интерфейс базового класса входит составной частью в интерфейс порожденного класса. Можно говорить о том, что приpublic– наследовании наследуется интерфейс базового класса.
При использовании protected– наследования иpublic– наследования интерфейс базового класса клиентам базового класса не предоставляется. В этом случае можно говорить о наследовании реализации.
Имеется ряд элементов базового класса, которые не наследуются. К их числу относятся:
конструкторы.
Деструктор.
Перегруженный оператор присваивания.
Основным видом наследования в языке C++ являетсяpublic– наследование. Именно при этом виде наследования реализуются все фундаме