Similar presentations:
Лекция 5 Наследование Часть 1
1.
Санкт-Петербургский государственныйархитектурно-строительный университет
кафедра информационных технологий
Объектно-ориентированное программирование
Тема 5
Наследование. Часть 1
Букунов Сергей Витальевич
к.т.н., доцент, доцент
2. Основные положения
Наследованием называется механизм, позволяющий одному классу(производному классу, подклассу) наследовать структуру данных и
поведение (методы) другого (базового класса, суперкласса) класса.
Наследование – это процесс создания новых классов, называемых
наследниками или производными классами, из уже существующих
(базовых) классов.
Базовый класс – это любой класс, который используется в качестве
основы для определения другого класса.
2
3. Иерархия классов
Наследование используется для отработки отношений иерархии вобъектном подходе: все общие свойства различных сущностей
объединены в некотором базовом (родительском) классе, а производные
классы наследуют все его свойства, добавляя свои собственные свойства
и поведение.
3
4. Пример наследования
UML-диаграмма иерархии классов4
5. Многоуровневое наследование
от одного базового класса можно унаследовать любое количествопроизводных классов;
производный класс может выступать в роли базового класса для других
классов.
класс Cat является прямым наследником класса Animal и непрямым
наследником класса Organism;
класс Organism является прямым базовым классом для классов Animal и
Plant и непрямым базовым классом для классов Cat и Dog.
5
6. Пример иерархии классов – библиотека потокового ввода-вывода C++
класс ios является базовым классом для всех потоковых классов;классы istream и ostream являются наследниками класса ios и предназначены для ввода/вывода;
класс iostream – наследник обоих классов istream и ostream (пример множественного наследования;
класс ifstream является производным классом от класса istream и предназначен для считывания данных из файлов;
класс ofstream является производным классом от класса ostream и предназначен для записи данных в файл.
6
7. Особенности наследования
механизм наследования работает только в одну сторону, аименно от производного класса к базовому. Пример: инженер –
это человек. Обратное же неверно: человек – это
необязательно инженер.
назначение наследования в объектно-ориентированном
программировании такое же, как и у функций в процедурном
программировании – сократить размер кода и упростить связи
между элементами программы.
разработанный класс может быть использован в других
программах. Это свойство называется возможностью
повторного использования кода. Аналогичным свойством в
процедурном программировании обладают библиотеки
функций, которые можно включать в различные программные
проекты.
7
8. Плюсы и минусы наследования
Главная польза от наследования – возможность повторногоиспользования существующего кода.
Пример. Постоянные обновления версий различного ПО
напрямую связаны с использованием механизма наследования.
Вносить так часто изменения в таких количествах в процедурную
программу без нарушения ее работоспособности было бы очень
проблематично.
Главная «расплата» за наследование – производные классы
наследуют все свойства и методы базового класса, т.е. нельзя
исключить из производного класса метод базового класса (если,
например, он там не нужен).
8
9. Ложные аналогии
Отношения «класс – объект» и «базовый класс – производныйкласс» – это «две большие разницы».
Объекты класса представляют собой воплощение свойств и
методов, присущих классу, к которому они принадлежат.
Производные классы имеют свойства как унаследованные от
базового класса, так и свои собственные.
9
10. Механизм наследования классов
1011. Синтаксис наследования в языке С++
A a; // создали объект a базового класса AB b; // создали объект b производного класса B
a.MethodA(); // объект a базового класса вызывает метод базового класса
b.MethodB(); // объект b производного класса вызывает метод производного класса
b.MethodA(); // объект b производного класса вызывает метод базового класса
a.MethodB(); // Ошибка !!! Объект a базового класса вызывает метод производного класса
11
12. Модификаторы наследования
Модификатор наследования определяет видимость наследуемыхполей и методов (т.е. полей и методов базового класса) для
производного класса и его возможных потомков. Таким образом
определяется, какие права доступа к полям и методам классародителя будут «делегированы» классу-потомку.
При реализации наследования область видимости принадлежащих
базовому классу данных и методов определяется одним из трех
модификаторов доступа:
private (закрытый);
public (открытый);
protected (защищенный).
12
13. Модификаторы доступа
Модификатор доступа private описывает закрытые члены класса,доступ к которым имеют только методы-члены этого класса.
Модификатор доступа public предназначен для описания
общедоступных элементов, доступ к которым возможен из любого
места программы, где доступен объект этого класса.
Модификатор доступа protected используется в тех случаях, когда
необходимо, чтобы некоторые члены базового класса оставались
закрытыми для внешнего окружения, но были бы доступны из
производного класса.
Вывод: при создании класса, который в дальнейшем будет
использоваться в качестве базового класса при наследовании,
данные, к которым нужно будет иметь доступ из производных
классов, следует объявлять со спецификатором доступа protected.
13
14. Модификаторы доступа в ситуации без наследования
1415. Модификаторы доступа в ситуации с наследованием
1516. Наследование и доступ
1617. Модификаторы наследования vs Модификаторы доступа
В языке С++ одни и те же ключевые слова используются и вкачестве модификаторов наследования и в качестве модификаторов
доступа.
Модификаторы наследования:
Модификаторы доступа:
- private
- private
- public
- public
- protected
- protected
class figure { …};
class circle : public figure
{ …};
class figure
{ public: int color;
…
};
17
18. Основные положения наследования
каждый объект производного класса включает в себя объектбазового класса, т.е. состоит из двух частей (своей части и
«базовой» части);
общедоступные (public) элементы базового класса являются
общедоступными элементами производного класса;
закрытые (private) элементы базового класса являются частью
производного класса, но обращаться к ним можно только
посредством общедоступных (public) и защищенных (protected)
методов базового класса;
при наследовании базовый класс остается неизменным;
от одного базового класса можно унаследовать любое количество
производных классов;
производный класс может выступать в роли базового класса для
других классов.
18
19.
Вопрос: какие члены базового класса наследуются в производномклассе, а какие не наследуются ?
19
20. Наследование членов базового класса в производном классе
2021. Конструкторы при наследовании
2122. Конструкторы при наследовании
При реализации наследования конструкторы базового и/илипроизводного класса могут иметь аргументы.
Если аргументы нужны только конструктору производного класса,
они передаются обычным образом.
Если требуется передать какие-либо аргументы родительскому
конструктору, для этого используется расширенная запись
конструктора производного класса:
Конструктор производного класса (список формальных аргументов):// Конструктор производного
Конструктор базового класса (список формальных аргументов)
// вызывает конструктор
{
// базового класса
… // тело конструктора производного класса
}
22
23. Конструкторы при наследовании
списки аргументов родительского и дочернего конструкторовмогут совпадать, а могут и отличаться. Например, конструктор
производного класса часто принимает некоторые аргументы
только для того, чтобы передать их конструктору базового класса;
если в базовом классе есть перегруженный оператор
присваивания, то он не наследуется производными классами. При
этом присваивание объектов производного класса не будет
вызывать ошибку – в этом случае выполняться будет не
перегруженный оператор базового класса, а присваивание по
умолчанию (т.е. будет запускаться конструктор копирования по
умолчанию производного класса), т.е. побитовое копирование
свойств объекта.
23
24. Деструкторы при наследовании
При реализации наследования в случае наличия деструкторов вбазовом и производном классах при уничтожении
объекта
производного класса деструкторы вызываются в обратном порядке:
сначала вызывается деструктор производного класса, т.е.
уничтожается часть объекта, принадлежащая производному
классу;
затем вызывается деструктор базового класса, т.е. уничтожается
часть объекта, принадлежащая базовому классу.
24
25. Наследование при работе с классом first
Задача. Необходимо добавить возможность осуществлять операциипрефиксного декрементирования с объектами класса first.
Вопрос: какие у нас есть варианты ?
25
26. Наследование при работе с классом first
Вариант №1. Модифицировать класс first, добавив в состав методовкласса соответствующий метод operator --().
Вариант №2. Создать новый класс, производный от класса first, и
добавить метод operator --() в состав методов этого производного
класса.
Вопрос: какие у нас могут быть мотивы для того, чтобы
использовать для решения этой задачи вариант №2 ?
26
27. Наследование при работе с классом first
Мотив №1. Класс first прекрасно работает, а на его отладку былозатрачено много времени и сил (предположим, что это так).
Мотив №2. Доступ к базовому классу first у нас отсутствует
(например, класс first распространяется как часть библиотеки
классов), следовательно прописать в нем какой-либо новый метод
мы не можем.
27
28. Наследование при работе с классом first
Вопрос: что не нравится компилятору ?28
29. Наследование при работе с классом first
Ответ: при любом типе наследования у производного класса нетдоступа к закрытым (private) членам базового класса.
Вопрос: как решить проблему ?
29
30. Наследование при работе с классом first
Вопрос: почему у метода класса second тип возвращаемого значения first ?30
31. Наследование при работе с классом first
Ответ: потому что в классе second отсутствует конструктор.31
32. Наследование при работе с классом first
Вопрос: почему в производном классе можно вызвать конструкторбазового класса ?
32
33. Наследование при работе с классом first
Ответ: потому что вcе методы из public-секции базового классадоступны производному классу.
33
34. Наследование при работе с классом first
Вопрос: какую из операций в функции main() не пропустит компилятор ?int main()
{
first f1; // создаем объект базового класса
second s1; // создаем объект производного класса
++f1; // инкрементируем объект базового класса
++s1; // инкрементируем объект производного класса
--f1; // декрементируем объект базового класса
--s1; // декрементируем объект производного класса
}
34
35. Наследование при работе с классом first
Вопрос: почему ++s1 можно, а --f1 нельзя ?35
36. Наследование при работе с классом first
Ответ: потому что наследование работает только в одномнаправлении: от производного класса к базовому:
производный класс знает всё о базовом классе;
базовый класс не знает о производном классе ничего.
36
37. Наследование при работе с классом first
Вопрос: что мы увидим на экране и почему ?37
38. Наследование при работе с классом first
Ответ: при отсутствии конструктора в производном классекомпилятор использует конструктор базового класса без
аргументов.
38
39. Конструкторы производного класса
Вопрос: что не нравится компилятору ?39
40. Конструкторы производного класса
Вопрос: что не нравится компилятору ?40
41. Конструкторы производного класса
Ответ: при инициализации объекта s2 компилятор пытаетсяиспользовать конструктор базового класса без аргументов (т.е.
конструктор first()).
Вопрос: как решить проблему ?
41
42. Конструкторы производного класса
Следствие №1. В функции main() всё хорошо.Следствие №2. Метод operator--() производного класса имеет тип
возвращаемого значения second, а не first (что более естественно).
42
43. Конструкторы производного класса
Замечание №1. В данном примере конструкторы производного класса дляинициализации полей объектов вызывают конструкторы базового класса .
Замечание №2. Кроме вызова конструктора базового класса конструктор
производного класса может выполнять и свои операции (просто в данном
43
случае этого не требуется).
44. Перегрузка методов базового класса в производном классе
При использовании наследования методам производного классаможно давать те же названия, что и методам базового класса. Т.е. в
этом случае может иметь место перегрузка функций.
Такая возможность может понадобиться в том случае, если в
программе для объектов базового и производного классов
используются одинаковые вызовы.
Общее правило: если названия методов базового и производного
классов совпадают, то при вызове метода для объекта производного
класса по умолчанию будет вызван метод производного класса. В
этом случае говорят, что метод производного класса перегружает
метод базового класса.
Вопрос. Какой метод будет вызван по умолчанию для объекта
базового класса ?
44
45. Перегрузка методов базового класса в производном классе
Вопрос. Может ли объект производного класса вызвать методбазового класса в том случае, если названия методов обоих классов
совпадают ?
45
46. Перегрузка методов базового класса в производном классе
Ответ: может, для этого необходимо явно вызвать метод базовогокласса.
46
47. Иерархия классов
Механизм наследования может использоваться не только длядобавления новых возможностей существующим классам, но и для
построения иерархии классов на этапе разработки программы.
47
48. Иерархия классов
Вопрос: почему в данном примере поля данных в базовом классе (классemployee) не обязательно объявлять в защищенной (protected) секции, а
48
можно объявить в закрытой (private) секции ?
49. Иерархия классов Иерархия классов Вопрос: какие методы getdata() будут вызывать объекты m1, p1, p2 и cw1 ?
Иерархия классовВопрос: какие методы getdata() будут вызывать объекты m1, p1, p2 и cw1 ?
49
50. Иерархия классов
Замечание. В программе не создано ниодного объекта базового класса employee
(но, в принципе, его можно создать).
Класс employee использовался только для
того, чтобы стать базовым классом для
других классов.
Такие классы иногда ошибочно называют
абстрактными классами.
50
51.
Санкт-Петербургский государственныйархитектурно-строительный университет
кафедра информационных технологий
Автор:
Букунов Сергей Витальевич
pmi@spbgasu.ru
programming