Лабораторна робота № 9
Тема: Відкрите спадкування.
Мета: Ознайомитись з відкритим спадкуванням
Теоретичні відомості:
Відкрите спадкування означає те, якщо клас D нащадок класу B, то об'єкт класу D є також об'єктом класу B, але не навпаки. Тому, скрізь де використовується клас, може бути використаний і клас D. Тобто В - загальна концепція, D - більш конкретна концепція. Відкрите спадкування припускає, що ВСЕ, що застосовується до об'єктів базового класу, можна застосувати і до об'єктів похідного класу. Наприклад клас квадрата не є відкритим нащадком класу прямокутника, тому що не всі властивості базового класу застосовні до похідному - у прямокутника бік можуть бути не рівні. Ідея відкритого спадкування складається з двох частин: успадкування інтерфейсу і успадкування реалізації. Різниця між ними аналогічно відмінності між оголошенням м визначенням. Інтерфейс функцій-членів успадковується завжди - тобто все що вірне для базового, вірно і для похідного. Всі функції-члени можна умовно розділити на три групи: 1) Чисто віртуальні функції - не визначаються в базовому класі (абстрактному) і повинні бути заново оголошені в будь-якому успадковане класі. Метою оголошення чисто віртуальної функції полягає в тому, щоб похідні класи наслідували тільки! її інтерфейс. Це можна інтерпретувати так: похідні класи повинні забезпечити наявність функції F (), але в базовому класі немає інформації про те, як вона буде працювати. Строго кажучи, дати визначення чисто віртуальної функції можливо, але викликати її можна через змінну, яка посилається на об'єкт похідного класу (створити екземпляр класу, що містить суто віртуальну функцію не можна), через вказівку перед функцією імені класу. Наприклад: Shape * p = new Rectangle; p-> Shape:: Draw (); / / Draw () - чисто віртуальна функція 2) Віртуальні функції - успадковуються похідними класами і забезпечують реалізацію, яку похідні класи можуть нехтувати. Метою оголошення віртуальної функції є спадкування похідними Власов як інтерфейсу, так і реалізації за замовчуванням. Це можна інтерпретувати так: похідні класи повинні підтримувати функцію F (), але якщо немає необхідності писати оригінальну реалізацію, можна взяти версію за замовчуванням з базового класу. 3) невіртуальний функції - мають однакову реалізацію у всіх похідних класах і не передбачається, що її буде перезавантажувати. Мета оголошення невіртуальному функції є нав'язування похідним класами як інтерфейсу, так і обов'язкової реалізації. З технічної точки зору віртуальні та невіртулаьние функції розрізняються типом зв'язування. Тобто часом коли програмі буде відомо, яку функцію викликати в даному фрагменті коду. Зв'язування буває статичним і динамічним. При статичному зв'язуванні, вибір потрібної функції визначається на основі статичного типу об'єкта, якому належить функція (тобто типу, зазначеного в коді). Статичне зв'язування відбувається на етапі компіляції, тому що статичний тип об'єкту зазначений спочатку. Динамічний тип об'єкта визначається типом об'єкта, на який він посилається в даний момент. Динамічний тип може змінюватися в ході виконання програми. Віртуальні функції зв'язуються динамічно. Динамічний і статичний типи мають сенс тільки для покажчиків. Т.ч. невіртулаьние функції для об'єкта має статичний тип pB, в незалежності від того, який тип має динамічний об'єкт будуть викликатися з класу B. Також, якщо pB оголошується як покажчик на об'єкт типу B, невіртуальний функції, що викликаються за допомогою pB - це завжди функції визначення, яких дані в класі B, навіть якщо РВ вказує на об'єкт класу похідного від В. Приклад: class D: public B (    public:      void mf (); / / невіртуальний і перевизначення функція ) D x; B y; B * pB = &x; D * pD = &x; pB-> mf (); / / Викликається функція B:: mf () pD-> mf () / / Викликається функція D:: mf () / / Викликаються різні функції, хоча покажчики посилаються на один і той самий об'єкт pD-> mf (); / / Викликається функція D:: mf () pD = &y; pD-> mf (); / / Викликається функція D:: mf () / / Викликається одна й та сама функція, хоча покажчик посилається на об'єкти різних типів Практично будь-який клас, який повинен використовуватися як базовий, буде містити віртуальні функції. Віртуальні функції зв'язуються динамічно, тобто динамічний тип об'єкта визначає яка функція буде викликана. Але при цьому значення аргументу за умовчанням для таких функцій визначаються за статичного типу. Для усунення такого недоліку можна скористатися ідіоми NVI - ідіоми невіртуального інтерфейсу. Її ідея полягає у твердженні, що всі віртуальні функції повинні бути закриті і викликатися у відкритих невіртуальний методах. Перевагою такого методу є те, що в невіртуальний функції, які не підлягають перевизначення можна включити код який обов'язково виконається до або після виклику віртуальної функції, незалежно від бажання клієнта. При цьому клієнт може змінити закриту віртуальну функцію, яку може викликати тільки через успадковану невіртуальний, але не напряму. Т.ч. клієнт може визначити що повинна робити перевизначається віртуальна функція, а базовий клас визначає коли ця функція буде викликана. Тобто можна визначити відкриту невіртуальний функцію із значенням за умовчанням і в ній викликати віртуальну функцію. Ще одна тонкість. У похідному класі не можна визначати функцію з тим же ім'ям і з тим же набором параметрів, але з іншим типом значення, що повертається, ніж у віртуальній функції базового класу. У цьому випадку компілятор налає на етапі компіляції програми. Далі. Якщо у похідному класі ввести функцію з тим же ім'ям і типом значення, що повертається, що і віртуальна функція базового класу, але з іншим набором параметрів, то ця функція похідного класу вже не буде віртуальною. Навіть якщо ви Супроводжується ключовим словом virtual, вона не буде тим, що ви очікували. У цьому випадку за допомогою покажчика на базовий клас при будь-якому значенні цього вказівника буде виконуватися звернення до функції базового класу. Згадайте правило про перевантаження функцій! Це просто різні функції. У вас вийде зовсім інша віртуальна функція. Взагалі кажучи подібні помилки дуже важковловимий, оскільки обидві форми запису цілком допустимі і сподіватися на діагностику компілятора у цьому випадку не доводиться. Звідси ще одне правило. При заміщенні віртуальних функцій потрібно повний збіг типів параметрів, імен функцій і типів повертаються значень у базовому і похідному класах. І ще. Віртуальної функцією може бути тільки нестатіческая компонентна функція класу. Віртуальної не може бути глобальна функція. Віртуальна функція може бути оголошена дружній
Хід роботи
Реалізувати відкрите наслідування наступних структурах:
«Спорт клубу».
«Бібліотеки».
«Обувного магазину»
«Булочної»
«Мобільного магазину»
Тощо…