Скачать презентацию Наследование классов и виртуальные функции 1 Механизм Скачать презентацию Наследование классов и виртуальные функции 1 Механизм

Лекция _5_Наследование.ppt

  • Количество слайдов: 58

Наследование классов и виртуальные функции Наследование классов и виртуальные функции

1. Механизм наследования. Простое наследование Наследование позволяет одним объектам получать свойства других объектов. Класс-наследник 1. Механизм наследования. Простое наследование Наследование позволяет одним объектам получать свойства других объектов. Класс-наследник ( в С++ это называется производный класс ) получает свойства родительского ( базового ) класса. Кроме этого, производный класс может добавлять к этим свойствам свои собственные.

Наследуются или не наследуются определённые поля и методы, определяется с помощью механизма наследования : Наследуются или не наследуются определённые поля и методы, определяется с помощью механизма наследования : public, private, protected. Механизм наследования private protected public Ключ доступа в базовом классе private protected public Доступ в производном классе нет private Нет protected public

При описании класса в его заголовке перечисляются все классы, являющиеся для него базовыми и При описании класса в его заголовке перечисляются все классы, являющиеся для него базовыми и может указываться механизм наследования (по умолчанию private): class имя: [private|protected|public]базовый_класс { }; тело_класса Например: class A {…}; class B {…}; class C {…}; class D: A, protected B, public C {…};

Простым называется наследование, при котором производный класс имеет одного родителя. Простым называется наследование, при котором производный класс имеет одного родителя.

Диаграмма классов A -х: int + y: int B + z: int +show(): void Диаграмма классов A -х: int + y: int B + z: int +show(): void

Поле x не наследуется (ключ доступа private), поле y наследуется. Внесём в программный код Поле x не наследуется (ключ доступа private), поле y наследуется. Внесём в программный код изменения: поле х объявим как protected, добавим метод set для установки значения поля х, изменим метод show.

Изменим механизм наследования, сделав его private. Тогда все поля и методы класса В будут Изменим механизм наследования, сделав его private. Тогда все поля и методы класса В будут закрытыми. Восстановим уровень доступа к элементам y и set:

Но процедура восстановления уровней доступа не вписывается в концепцию инкапсуляции. Поэтому лучше воспользоваться переопределением Но процедура восстановления уровней доступа не вписывается в концепцию инкапсуляции. Поэтому лучше воспользоваться переопределением методов или виртуальной функцией.

2. Переопределение методов и виртуальные функции Рассмотрим идею полиморфизма на примере: У класса А 2. Переопределение методов и виртуальные функции Рассмотрим идею полиморфизма на примере: У класса А есть поле x, методы set() и get(). Путём public-наследования создаётся класс B, в котором содержится дополнительное поле y. Логично, чтобы set() и get() оперировали не только полем x, но и y. Т. е. методы set() и get() в производном классе надо переопределить. Тогда в базовом классе эти методы надо определить как виртуальные (virtual).

Разница между переопределением и перегрузкой: при перегрузке меняется прототип метода, при переопределении – нет. Разница между переопределением и перегрузкой: при перегрузке меняется прототип метода, при переопределении – нет.

Если бы методы set() и get() не были бы объявлены как виртуальные, то вызывались Если бы методы set() и get() не были бы объявлены как виртуальные, то вызывались бы всегда методы базового класса. Инструкция virtual используется только в классе A – виртуальность метода наследуема. Поэтому в дальнейшем при переопределении метода в классах, производных от В, метод останется виртуальным.

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

Результаты работы программы: В главной функции программы создаются объекты всех четырёх классов, из каждого Результаты работы программы: В главной функции программы создаются объекты всех четырёх классов, из каждого объекта вызывается метод set() и метод get(). При вызове из объекта класса A вызываются методы этого класса. При вызове из объекта класса B метод set() вызывается «родной» , а метод get() – из класса A. При вызове из объекта класса C метод set() вызывается из класса B, а метод get() – «родной» . При вызове из объекта класса D метод set() вызывается из класса B, а метод get() – из класса С.

Диаграмма классов A D +k: int +n: int +set(n: int): void +get(): void B Диаграмма классов A D +k: int +n: int +set(n: int): void +get(): void B +set(n: int): void +get(): void C +m: int +set(n: int): void +get(): void +set(n: int): void

4. Многократное наследование В С++ класс может создаваться на основе сразу нескольких классов (многократное 4. Многократное наследование В С++ класс может создаваться на основе сразу нескольких классов (многократное наследование). При многократном наследовании указывают через запятую базовые классы и механизм наследования для каждого класса. Пример многократного наследования:

При многократном наследовании могут возникать проблемы с неоднозначностью наследования членов базового класса. Пусть, например, При многократном наследовании могут возникать проблемы с неоднозначностью наследования членов базового класса. Пусть, например, наследуемые поля классов А и В имеют одинаковые названия – n. При обращении к таким полям необходимо явно указывать, из какого класса они наследованы. Если obj является объектом класса C, то к полю от класса А можно обратиться, как obj. A: : n.

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

Поскольку классами B и С наследование класса А выполняется виртуально, то дублирования поля n Поскольку классами B и С наследование класса А выполняется виртуально, то дублирования поля n в классе D нет.

5. Конструкторы и деструкторы при наследовании В производном классе надо предусмотреть механизм передачи аргументов 5. Конструкторы и деструкторы при наследовании В производном классе надо предусмотреть механизм передачи аргументов конструктору базового класса. Этот механизм таков: при определении конструктора производного класса после имени конструктора указывается имя конструктора базового класса со списком аргументов.

Синтаксис объявления конструктора производного класса: Имя_констр(аргументы): Имя_констр1(аргументы), Имя_констр2(аргументы), . . . { // Код Синтаксис объявления конструктора производного класса: Имя_констр(аргументы): Имя_констр1(аргументы), Имя_констр2(аргументы), . . . { // Код конструктора производного класса } Пример определения конструктора при наследовании:

В производном классе Derivative надо предусмотреть механизм передачи аргументов конструктору базового класса. Причина в В производном классе Derivative надо предусмотреть механизм передачи аргументов конструктору базового класса. Причина в способе создания объектов производных классов: сначала вызывается конструктор базового класса, а затем – производного. Если базовых классов несколько, то их конструкторы вызываются в порядке наследования классов (очерёдность в списке наследуемых классов слева направо).

В конструкторе Derivative предусмотрена передача двух аргументов: один передаётся конструктору базового класса, а второй В конструкторе Derivative предусмотрена передача двух аргументов: один передаётся конструктору базового класса, а второй – конструктору производного класса. Далее приведён пример определения конструктора производного класса при многократном наследовании:

В результате выполнения программы получим: В результате выполнения программы получим:

Конструкторы вызываются в такой последовательности: конструктор класса Base 1, конструктор класса Base 2, конструктор Конструкторы вызываются в такой последовательности: конструктор класса Base 1, конструктор класса Base 2, конструктор класса Derivative. Деструкторы вызываются в обратной последовательности: деструктор Derivative, деструктор Base 2, деструктор Base 1.

6. Чисто виртуальные методы и абстрактные классы Чисто виртуальной функцией называется такая виртуальная функция, 6. Чисто виртуальные методы и абстрактные классы Чисто виртуальной функцией называется такая виртуальная функция, которая не имеет определения в базовом классе. Синтаксис объявления чисто виртуальной функции в базовом классе: virtual тип_результата имя_функции(аргументы)= 0; Класс, содержащий хотя бы одну чисто виртуальную функцию, называется абстрактным.

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

Создаётся абстрактный класс Figure c полем R (линейный размер геометрической фигуры), конструктором и чисто Создаётся абстрактный класс Figure c полем R (линейный размер геометрической фигуры), конструктором и чисто виртуальной функцией area() для вычисления площади фигуры. На основе этого базового класса создаются 3 производных класса, где метод area() переопределяется.

Диаграмма классов Figure +R: double +Figure(R: double) +area(): virtual double Circle Square Triangle +area(): Диаграмма классов Figure +R: double +Figure(R: double) +area(): virtual double Circle Square Triangle +area(): double

7. Примеры решения задач Все те вопросы, которые были поставлены, мы их все соберём 7. Примеры решения задач Все те вопросы, которые были поставлены, мы их все соберём в одно место. В. С. Черномырдин. Задача 1 Создать класс для реализации алгебраической формы комплексного числа. Создать производный класс, который использует тригонометрическое представление комплексного числа. Напомним: алгебраическая форма : z = x + i y, Тригонометрическая форма : z = r ∙exp( i φ). x = r ∙ cos φ ; y = r ∙ sin φ ; tg φ = y / x

Результат выполнения программы: Результат выполнения программы:

Базовый класс Compl. Alg: для работы с полями x и y используются виртуальные методы Базовый класс Compl. Alg: для работы с полями x и y используются виртуальные методы set() и show(). Конструктор без аргументов создаёт нулевое комплексное число, а конструктор с аргументами позволяет задать x и y. Производный класс Сompl : добавляются модуль r и угол phi. Методы set() и show() переопределяются. В каждом из этих методов сначала вызывается старая версия метода из базового класса, а затем метод расширяется для работы с тригонометрической формой записи.

Задача 2 Создать класс Polynom 1 для реализации полиномов степени ≤ n. Для реализации Задача 2 Создать класс Polynom 1 для реализации полиномов степени ≤ n. Для реализации вычисления произведения двух полиномов степени ≤ n создать производный класс Polynom 2 (для полиномов степени ≤ 2 n).

Если полином умножается на , то получим полином: Для записи коэффициентов для x степени Если полином умножается на , то получим полином: Для записи коэффициентов для x степени больше n в производном классе определяется массив b. Путём переопределения операторной функции [ ] выполняется индексация элементов массива.

Оператор () перегружается в базовом классе для вычисления значения полинома, а в производном классе Оператор () перегружается в базовом классе для вычисления значения полинома, а в производном классе этот оператор переопределяется с учётом расширенного набора коэффициентов. Произведение полиномов вычисляется с помощью внешней операторной функции *. При выполнении умножения P 3=P 1*P 2 коэффициенты старших слагаемых степени от n+1 до 2 n теряются. Это можно применить для вычисления рядов Тейлора для различных функций.