НОУ ІНТУІТ, Лекція, Похідні класи, успадкування

Тепер ми визначили метод Name як суто віртуальний. Клас, у якого є хоча б один суто віртуальний метод, називається абстрактним.

Якщо метод оголошений суто віртуальним, отже, він має бути визначений у всіх класах, похідних від Item. Наявність суто віртуального методу забороняє створення об'єкта типу Item. У програмі можна використовувати покажчики або посилання тип Item . Записи

не дозволено, і компілятор повідомить про помилку. Однак можна записати:

Зазначимо, що, визначивши суто віртуальний метод у класі Book, у наступному рівні успадкування його вже не обов'язково перевизначати (у класах, похідних із Book).

Якщо з якихось причин у похідному класі суто віртуальний метод не визначено, цей клас теж буде абстрактним , і будь-які спроби створити об'єкт даного класу викликатимуть помилку. Таким чином, забути визначити суто віртуальний метод просто неможливо. Абстрактний базовий клас нав'язує певний інтерфейс усім похідним із нього класам. Власне, у цьому полягає головне призначення абстрактних класів – у визначенні інтерфейсу для всієї ієрархії класів. Зрозуміло, це означає, що у абстрактному класі може бути певних методів чи атрибутів.

Взагалі, клас можна зробити абстрактним, навіть якщо всі його методи визначені. Іноді це необхідно зробити для того, щоб бути впевненим у тому, що об'єкт цього класу ніколи не буде створений. Можна задати один із методів як суто віртуальний, але, проте, визначити його реалізацію. Зазвичай з цією метою вибирається деструктор :

Клас A – абстрактний, і об'єкт типу A створити неможливо. Однак деструктор його визначено і буде викликано при знищенніоб'єктів похідних класів (про порядок виконання конструкторів та деструкторів див. нижче).

Множинне успадкування

У мові Сі++ є можливість базових задати кілька класів. У такому разі похідний клас успадковує методи та атрибути всіх його батьків. Приклад ієрархії класів у разі множинного наслідування наведено на наступному малюнку.

лекція

В даному випадку клас C успадковує двом класам, A та B .

Множинне наслідування – потужний засіб мови. Наведемо деякі приклади використання множинного успадкування.

Припустимо, існуючу бібліотечну систему вирішено встановити в університеті та інтегрувати з іншою системою обліку викладачів та студентів. У бібліотечній системі є класи, що описують читачів та працівників бібліотеки. У системі обліку кадрів існують класи, що зберігають інформацію про викладачів та студентів. Використовуючи множинне наслідування, можна створити класи студентів-читачів, викладачів-читачів та студентів, які підробляють бібліотекарями.

Об'єкт класу AnnotatedSquare має метод GetText, успадкований від класу Annotation, він визначає віртуальний метод Draw, успадкований від класу Shape.

При застосуванні множинного успадкування виникає низка проблем. Перша їх – можливий конфлікт імен методів чи атрибутів кількох базових класів .

неможливо визначити, до якого із двох методів fun відбувається звернення. Ситуація називається неоднозначною і компілятор видасть помилку. Зауважимо, що помилка видається не визначенні класу C , у якому закладено можливість виникнення неоднозначної ситуації, лише при спробі виклику методу fun .

Неоднозначність можна дозволити, явно вказавши, до якого збазових класів відбувається звернення:

Друга проблема полягає у можливості багаторазового включення базового класу. У згаданому вище прикладі інтеграції бібліотечної системи та системи кадрів цілком імовірна ситуація, за якої класи для працівників бібліотеки та для студентів були виведені з того самого базового класу Person :

Якщо тепер створити клас для представлення студентів, які підробляють у бібліотеці

то об'єкт даного класу міститиме об'єкт базового класу Person двічі (див. рисунок 10.3).

Крім того, що подібна ситуація відображає нераціональне використання пам'яті, жодних незручностей у цьому випадку вона не викликає. Можливу неоднозначність можна дозволити, явно вказавши клас:

Проте іноді необхідно, щоб об'єкт базового класу містився у похідному один раз. Для цих цілей застосовується віртуальне наслідування, мова про яке попереду.

Віртуальне успадкування

Базовий клас можна оголосити віртуальним базовим класом, використовуючи запис:

Гарантовано, що об'єкт віртуального базового класу міститиметься в об'єкті виведеного класу (див. рис. 10.4) один раз. Платою за віртуальність базового класу є додаткові накладні витрати при зверненнях до його атрибутів та методів наслідування.