1.80M
Category: programmingprogramming

Наследование

1.

Наследование
1. Особенности.
2. Открытые, защищенные и закрытые
элементы.
3. Конструкторы и деструкторы при
наследовании.
4. Множественное наследование

2.

Наследование
• Наследование – это способ повторного
использования кода, при котором новые классы
создаются на базе существующих классов путем
заимствования их элементов (данных и функций).
• Новый класс объявляется наследником ранее
определенного класса (базового класса).
• Новый класс называют производным классом.
• Производный класс может стать базовым для
других классов.
• Таким образом создается иерархия классов.

3.

Понятие наследования
Базовый класс
Производный класс
Наследование — важная составляющая концепции объектноориентированного программирования, благодаря которой возможно
создание новых классов на базе уже существующих.
Новые классы (производные) получают все элементы наследуемых
классов (базовых).

4.

Базовые и производные классы
Polygon
Quadrangle
Rectangle
Square
Rhombus
Triangle
Parallelogram
IsoscelesTriangle
RightTriangle
• Наследование порождает иерархические
древовидные структуры данных. В них всегда
можно добавить новый класс в требуемом месте.

5.

Простое и множественное наследования
Простое наследование
Базовый
класс
Производный
класс
Производный
класс
Множественное наследование
Базовый
класс
Базовый
класс
Производный
класс
При простом наследовании производный класс имеет только один
базовый класс. Базовый класс может иметь несколько производных
классов. Иерархия классов имеет вид дерева.
При множественном наследовании производный класс имеет несколько
родительских классов. Иерархия классов имеет вид ориентированного
графа.

6.

Преимущества наследования
1) Повторное использование программ
2) Использование общего кода
3) Согласование интерфейса
4) Программные компоненты
5) Быстрое макетирование
Недостатки наследования
1) Скорость выполнения
2) Размер программ
3) Сложность программ

7.

сlass имя_производного_класса :
атрибут_наследования
имя_базового_класса { … };

8.

Спецификаторы доступа в ситуации без
наследования

9.

Спецификаторы доступа в ситуации с наследованием
Public — доступ открыт всем, кто видит определение данного класса.
Protected — доступ открыт классам, производным от данного. То есть, производные
классы получают свободный доступ к таким свойствам или метода. Все другие классы
такого доступа не имеют.
Private — доступ открыт самому классу (т.е. функциям-членам данного класса) и друзьям
(friend) данного класса - как функциям, так и классам. Однако производные классы не
получают доступа к этим данным совсем. И все другие классы такого доступа не имеют.

10.

Наследование и доступ

11.

Модификаторы наследования
сlass имя_производного_класса : атрибут_наследования имя_базового_класса { … };
Атрибут наследования определяется тремя известными ключевыми словами: private, public и
protected, которые использовались для доступа к внутренним компонентам класса.
Вид
наследования
private
protected
public
Объявление поля в
базовом классе
Видимость в
производном классе
private
не видимо
protected
private
public
private
private
не видимо
protected
protected
public
protected
private
protected
public
не видимо
protected
Public
11

12.

Пример
class Parent
{
public:
int m_public;
private:
int m_private;
protected:
int m_protected;
};
class D2 : private Parent // закрытое наследование
{
// Закрытое наследование означает, что:
// члены public становятся private в дочернем классе;
// члены protected становятся private в дочернем классе;
// члены private недоступны для дочернего класса.
public:
int m_public2;
private:
int m_private2;
protected:
int m_protected2;
};

13.

14.

Особенности производного класса
• Обычно производный класс (ПК) содержит больше
данных и функций, чем базовый класс (БК). Он
наследует элементы БК и добавляет собственные.
• ПК более специализирован, специфичен в своей
области, представляет меньшее количество объектов.
• Объект производного класса также является объектом
базового класса. Но объект базового класса не является
объектом производного класса.
• В C++ возможны три вида наследования: открытое
(public), защищенное (protected) и закрытое (private).

15.

Особенности производного класса
• В БК можно использовать спецификатор доступа
protected.
• ПК не имеет прямого доступа к закрытым
элементам БК.
• ПК имеет прямой доступ к открытым и
защищенным элементам БК.
• Если у БК есть друзья, то производный класс их не
наследует.

16.

Базовые и производные классы
NSTUMember
Worker
Administrator
Student
Scientist
Teacher
• Синтаксис определения наследования:
class Worker : public NSTUMember { …
• Класс может быть базовым прямо и косвенно:
Для Teacher прямым базовым классом является Worker,
а косвенным – NSTUMember.

17.

Наследование
class Base {
int x;
public:
void setX(int n) { x = n; }
void showX() {cout << x << ' '; }
};
class Derived : public Base {
int y;
public:
void setY(int n) { y = n; }
void showY() {cout << y << ' '; }
};
int main() {
Base ob;
ob.setX(5);
ob.showX();
Derived od;
od.setX(10);
od.setY(20);
od.showX();
od.showY();
return 0;
Base
Derived
}

18.

Управление видимостью компонентов базового класса в производном
Производный класс может получить доступ к компонентам секций protected и public базового класса даже при
самом жестком виде наследования private. Для этого используют квалификатор доступа <Имя класса>::<Имя
компонента>. Квалификатор следует поместить в ту же секцию, в которой необходимый компонент был описан
в базовом классе.

19.

Конструкторы и деструкторы при наследовании
Правило вызова конструкторов и деструкторов при одиночном наследовании.
При создании экземпляра производного класса сначала выполняется
конструктор базового, а затем производного класса.
Деструкторы выполняются в обратном порядке.
При создании объекта базового класса выполняются конструктор и деструктор
только для данного базового класса.
Конструкторы производных и базового классов могут иметь аргументы.
Для того, чтобы осуществить передачу аргументов для конструктора базового
класса необходимо воспользоваться следующей записью:
конструктор_производного_класса (аргументы) : конструктор_базового_класса (аргументы)
19

20.

Если конструкторы базовых классов не имеют аргументов, то производный класс
может не иметь конструктора. При наличии у конструкторов базового класса
аргументов производный класс обязан иметь конструктор со списком
инициализации следующего вида:

21.

Порядок работы конструкторов базового и производного классов.

22.

Наследование на примере класса «счетчик»

23.

Множественное наследование
Язык С++ позволяет осуществлять наследование не только от одного, но и
одновременно от нескольких классов. Такое наследование получило название
множественного. Описание производного класса при множественном
наследовании выглядит следующим образом:

24.

Наследование в С++
Класс А
Класс В
Класс С
class A
{
...
};
class B
{
...
};
class C : public A, public B
{
...
};
Ограничение доступа при
наследовании

25.

26.

Множественное наследование
NSTUMember
Worker
Administrator
Student
Scientist
Teacher
AdminTeacher
ScTeacher
class ScTeacher : public Teacher, public Scientist { …
class AdminTeacher : public Teacher,
public Administrator { …

27.

Методы классов и множественное наследование
В классе student содержатся сведения о
школе или университете, которые
за кончил студент, и об уровне
полученного им образования.
Информация об образовании нужна
только для ученых и менеджеров.

28.

29.

30.

31.

Пример. Наследование от двух базовых классов. В данном примере
класс third наследуется от классов first и second
Множественное наследование
Объект класса third состоит из следующих полей:
· поля num_f, унаследованного от класса first (описанного public, наследованного private,
следовательно доступного private) и инициализированного случайным числом
· полей num_s и c_s, унаследованных от класса second (описанных public, наследованных public,
следовательно доступного public) и инициализированных числами 50 и символом «R», причем
инициализация поля c_s в конструкторе класса second не предусмотрена, поэтому она выполняется в
теле конструктора класса third.

32.

33.

Конфликты при множественном наследовании
class A1
{
public:
int
void
};
class A2
{
public:
int
void
};
a;
Func();
a;
Func();
class B : public A1, public A2
{
...
};
void main()
{
B b;
b.a = 5;
b.Func();
b.A1::a = 6;
b.A1::Func();
b.A2::a = 7;
b.A2::Func();
}
//
//
//
//
//
//
Ошибка
Ошибка
Правильно
Правильно
Правильно
Правильно
Для устранения конфликтов имен
при множественном наследовании
используется оператор расширения
области видимости

34.

Неопределенность при множественном наследовании

35.

сlass D
{
};
class B: public D
{
};
class C: public D
{
};
class A: public B, public C
{
};

36.

Пример. Проектирование классов с использованием наследования (классы
Целое число и Вещественное число).
Пусть требуется разработать классы для реализации объектов Целое число и
Вещественное число. Объект Целое число должен хранить длинное целое в
десятичной записи и уметь выводить его значение. Объект Вещественное
число должен хранить вещественное число, задаваемое в виде ccccc.dddddd,
и его символьное представление.
Он также должен уметь выводить свое значение на экран. Для обоих
объектов необходимо предусмотреть возможность инициализации как в
момент объявления переменной, так и в процессе функционирования.
Поскольку вещественное число включает длинное целое как целую часть,
класс для его реализации можно наследовать от класса, реализующего
длинное целое число.
Наследование классов

37.

38.

39.

Виртуальное наследование
Возможна ситуация, когда производный класс при наследовании от потомков
одного базового класса многократно наследует одни и те же компоненты
базового класса.
Иными словами, производный класс будет содержать несколько копий полей
одного базового класса.
Многократное наследование полей базового класса

40.

Виртуальное наследование
Чтобы избежать многократного включения в производный класс
компонентов базового класса, используется виртуальное наследование. При
виртуальном наследовании производный класс описывают следующим
образом:
В этом случае включение в производный класс полей базового класса осуществляется один раз, а их
инициализация выполняется в производном классе, который не является прямым потомком
базового класса.
Вызов конструкторов при этом происходит в следующем порядке: сначала конструктор виртуально
наследуемого базового класса, затем конструкторы базовых классов в порядке их перечисления
при объявлении производного класса, за ними – конструкторы объектных полей и конструктор
производного класса.
Деструкторы соответственно вызываются в обратном порядке.
Виртуально наследуемый класс обязательно должен содержать конструктор без
параметров, который активизируется при выполнении конструкторов классов – прямых
потомков виртуально наследуемого класса.

41.

Виртуальное наследование.
Реализуем иерархию классов. Класс derived наследуется от двух наследников класса fixed.
Чтобы исключить удваивание полей, описанных в классе fixed, необходимо использовать
виртуальное наследование.

42.

Включение: классы в классах
Включение называют взаимоотношением типа «имеет». Мы говорим, что
библиотека имеет книги (в библиотеке есть книги) или накладная имеет строки (в
накладной есть строки). Включение также называют взаимоотношением типа
«часть целого»: книга является частью библиотеки.
В ООП включение появляется, когда один объект является атрибутом другого
объекта. Рассмотрим случай, когда объект класса A является атрибутом класса B:

43.

Включение: классы в классах
Включение называют взаимоотношением типа «имеет». Мы говорим, что
библиотека имеет книги (в библиотеке есть книги) или накладная имеет строки (в
накладной есть строки). Включение также называют взаимоотношением типа
«часть целого»: книга является частью библиотеки.
В ООП включение появляется, когда один объект является атрибутом другого
объекта. Рассмотрим случай, когда объект класса A является атрибутом класса B:

44.

45.

46.

47.

Композиция: сложное включение
Композиция — это более сложная форма объединения. Она обладает всеми его
свойствами, но имеет еще и такие, как:
♦ часть может принадлежать только одному целому;
♦ время жизни части то же, что и целого.

48.

Пример. Использование композиции для реализации включения
объектов.
Построим класс Вещественное число на базе класса Целое число, используя не
наследование, а композицию.
В классе предусмотрим три конструктора:
· пустой без параметров – на случай создания неинициализированных объектов;
· инициализирующий – создает объект по записи числа;
· инициализирующий – создает объект, получая отдельно целую и дробную части
числа.

49.

50.

Среда разработки Microsoft Visual C++ . Работа с клавиатурой.
При запуске вашей программы, главное окно должно будет выглядеть так

51.

52.

Связывание событий с элементами управления
Свяжите код с событием WM_KEYDOWN клавиатуры. При нажатии на клавишу будет появляться окно
сообщения, которое будет показывать ее флаг.
Добавьте в функцию следующий код

53.

Параметры функции OnKeyDown:
(UINT nChar, UINT nRepCnt, UINT nFlags)
nChar - показывает код нажатой клавиши.
nRepCnt - представляет число повторных нажатий на клавишу. Например, если вы
долго удерживаете клавишу B, то этот параметр сохранит кол-во нажатий на эту
клавишу.
nFlags представляет число нажатой специальной клавишы(такие как ALT, SHIFT).
Код, который объявляет три строки:
char strnChar[10];
char strnRepCnt[10];
char strnFlags[10];
Они будут хранить значения переменных nChar, nRepCnt, nFlags соответственно.
Функция itoa переводит число в текстовую строку.

54.

55.

Программа для пересчета из градусов в радианы.

56.

Добавим переменную, которая будет отвечать за «Поле редактирования».

57.

Добавить #include "tchar.h"

58.

59.

Расположим на диалоговом окне следующие элементы
• три метки (Static Text) для вывода заголовков полей;
• три поля редактирования (Edit Control);
• один элемент Group Box;
• две радиокнопки (Radio Button) для выбора типа уравнения;
• флажок (Check Box), определяющий как будет происходить вывод;
• метку для вывода результатов;
• кнопки для решения уравнения и выхода из программы;

60.

Определим переменные для полей редактирования, радиокнопок и
флажка. Щелкаем правой кнопкой мыши по первому полю ввода,
выбираем «Добавить переменную…». Заполняем окно так, как это сделано
на скриншо-те.
Аналогично добавляем переменные для двух оставшихся полей
(m_EditB, m_EditC).

61.

определение переменных для радиокнопок. Заходим в свойства элемента
GroupBox и устанавливаем значение «Группа»->True. То же самое делаем и
для обоих радиокнопок, после чего определяем имя и тип переменных для
них (рис. ниже).

62.

Установка свойства Group в True была необходима для того, чтобы можно было
создать переменные как экземпляры класса RadioButton. Но если мы сейчас
запустим программу, то переключения между кнопками не будет. Поэтому
установим у второй радиокнопки свойство Group в True.
При работе с группой радиокнопок нужно установить у них свойство Group в True,
после чего назначить переменные для всех кнопок, а затем установить у всех
кроме первой значение False .
Определим переменную, которая будет отвечать за значок, ее тип BOOL.

63.

Изменим значение ID четвертой метки (расположена над кнопкой «Решить») на
IDC_STATIC1. Определим переменную, отвечающую за работу с этой меткой
(рис. ниже).

64.

Переопределяем ID кнопки «Решить», впишем например ID_Solve.
Щелкаем два раза левой кнопкой мыши по кнопке «Решить», и попадаем в
окно с кодом. Тут подключаем библиотеку math.h, после чего вводим в
функцию OnBnClickedSolve() следующий текст.
English     Русский Rules