- •Передмова
- •Розділ 1 об'єктний підхід у програмуванні
- •1.1.Причини виникнення ооп
- •1.1.1.Складність об'єкта дослідження
- •1.1.2.Складність процесу розробки програмного забезпечення
- •1.1.3.Складність опису окремих елементів
- •1.2.Парадигма ооп
- •1.3.Історія розвитку ооп
- •Розділ 2 об'єкти й класи: інкапсуляція
- •2.1.Структура об'єкта й класу
- •2.2.Особливості опису класів у мовах ооп
- •2.2.1.Опис класів в SmallTalk
- •2.2.3.Опис класів в Delphi
- •2.2.4.Опис класів в Java
- •2.3.Поля даних та їх ініціалізація
- •2.3.1.Визначення полів даних в SmallTalk
- •2.3.3.Визначення полів даних в Delphi
- •2.3.4.Визначення змінних в Java
- •2.4.Доступ до даних
- •2.4.1.Доступ до даних в SmallTalk
- •2.4.3.Доступ до даних в Delphi
- •2.4.4.Доступ до даних в Java
- •2.5.Спеціальні змінні
- •2.5.1.Спеціальні змінні в SmallTalk
- •2.5.3.Спеціальні змінні в Java
- •2.5.4.Спеціальні змінні в Delphi
- •2.6.Посилання
- •2.6.1.Визначення посилань в SmallTalk, Delphi і Java
- •2.7.Методи
- •2.7.1.Загальна схема визначення методу
- •2.7.2.Визначення методів в SmallTalk
- •2.7.4.Визначення методів в Delphi
- •2.7.5.Визначення методів в Java
- •2.8."Дружні" методи
- •2.8.2.Аналог дружніх функцій в Delphi
- •2.9.Конструктори й деструктори
- •2.9.1.Конструктори й деструктори в SmallTalk
- •2.9.3.Конструктори й деструктори в Delphi
- •2.9.4.Конструктори й деструктори в Java
- •2.10.Властивості
- •2.10.1.Властивості в Delphi
- •2.10.2.Властивості в Java
- •2.12.Абстрактні методи
- •Розділ 3 успадкування
- •3.1.Форми успадкування
- •3.2.Успадкування в SmallTalk
- •3.3.1.Віртуальне успадкування
- •3.3.2.Правило сумісності типів
- •3.3.3.Використання конструкторів і деструкторів при успадкуванні
- •3.4.Успадкування в Delphi
- •3.4.1.Ієрархія класів в Delphi
- •3.4.2.Створення нових компонентів
- •3.5.Успадкування в Java
- •3.5.1.Використання ключового слова super
- •3.5.2.Клас Object
- •Розділ 4 поліморфізм
- •4.1.Віртуальні методи
- •4.2.1.Механізм пізнього зв'язування
- •4.2.2.Таблиця віртуальних методів
- •4.3.Поліморфізм в Delphi
- •4.3.1.Заміщення віртуальних і динамічних методів
- •4.3.2.Приведення типів
- •4.4.Поліморфізм в Java
- •4.5.Поліморфізм в SmallTalk
- •5.1.Потокові класи
- •5.1.1.Ієрархія потокових класів
- •5.1.2.Форматоване введення/ виведення
- •5.1.3.Маніпулятори
- •5.1.4.Введення/виведення у файл
- •5.2.Контейнерні класи
- •5.2.1.Ітератори
- •5.2.2.Визначення контейнерних класів
- •5.2.3.Стандартні контейнерні класи
- •5.3.1.Параметиізовані класи (шаблони)
- •5.3.2.Ітератори stl
- •5.3.3.Узагальнені алгоритми
- •Література
- •Додатки лабораторна робота №1 об'єкти й повідомлення в smalltalk
- •Лабораторна робота №2 класи й методи в smalltalk
- •Листинг 3.1
- •Листинг 3.2
- •Листинг 3.3
- •Лабораторна робота 5 компоненти в delphi
- •Лабораторна робота 6 меню й вікна в delphi
- •Лабораторна робота 7 розробка меню в java
- •Лабораторна робота 8 робота з подіями в java
3.3.1.Віртуальне успадкування
При множинному спадкуванні базовий клас не може бути заданий у похідному класі більше одного разу:
class D: A, B, B {...…}; // не припустимо
Однак базовий клас може бути переданий похідному класу більше одного разу побічно, наприклад, у такий спосіб:
class A {public: int i;};
class B: public A {...…};
class З: public A {...…};
class В: public B, public C {...…};
У наведеному прикладі кожний об'єкт класу D буде мати у своєму складі два об'єкти класу А. Це може привести до того, що при звертанні до змінного i класу А об'єкт класу D не буде знати змінну якого саме об'єкта класу А викликати. Для виключення даної колізії в передбачений варіант віртуального успадкування, коли для об'єкта-спадкоємця створюється не більше одного об'єкта кожного з наслідуваних класів. Для визначення віртуального успадкування перед ім'ям базового класу ставиться слово virtual:
class B: virtual public A {...…};
class З: virtual public A {...…};
С
уть
механізму віртуального успадкування
полягає в тому, що при віртуальному
успадкуванні об'єкт похідного класу
містить схований покажчик на об'єкт
віртуального базового класу. Цей покажчик
компілятор неявно використовує для
доступу до даних, успадкованих від
віртуального базового класу. Схема
побудови об'єкта похідного класу при
звичайному й віртуальному успадкуванні
показана на рис.3.5.
а) б)
Рис. 3.4. Схема побудови об'єкта похідного класу при звичайному й віртуальному спадкуванні: а) при звичайному спадкуванні, б) при віртуальному спадкуванні
3.3.2.Правило сумісності типів
Завдяки механізму успадкування, виникає можливість неявного перетворення типів, використовуючи для цього покажчики на базові класи. Правило сумісності типів при цьому полягає в наступному:
Якщо клас У має public базовий клас А, то значення покажчика на клас У можна привласнити змінної типу “покажчик на клас А” без явного перетворення типів. Тобто, покажчик на нащадка може одночасно бути покажчиком на предка, але не навпаки; зворотне перетворення повинне бути явним:
сlass A {...…………};
сlass B: public A {...…………};
void main() {
B b;
A * aptr = &b; // неявне перетворення типів
B* bptr = aptr; // помилка
bptr = (B*) aptr; // явне перетворення типів
}
Якщо базовий клас є private, то неявне приведення типів від нащадка до предка не робиться, тому що до загального елемента класу А є доступ тільки через покажчик на А, а не через покажчики на В:
сlass A { int m1;
public:
int m2;
…………};
class B: A {...…………};
void main()
{B b;
b..........2 = 2; // помилка, тому що m2 стала private
A* aptr = &b; // помилка
aptr = (A*) &b; // явне перетворення типів
aptr( m2 = 2; // допускається, тому що для покажчика aptr m2 public.
}
Таким чином, використовуючи явне перетворення типу можна обійти правило захисту доступу, але не можна одержати доступ до закритих змінним класу.
3.3.3.Використання конструкторів і деструкторів при успадкуванні
Механізм успадкування вносить свої особливості у використання конструкторів і деструкторів:
Коли клас має один або більше базових класів, конструктори базових класів запускаються до того, як будуть викликані конструктори похідних класів. Причому конструктори базових класів викликаються в тій послідовності, у якій вони присутні при оголошенні базових класів. Так, для класу, оголошеного, як
сlass X: public Y, public Z {...…};
послідовність виклику конструкторів буде наступною:
Y(); Z(); X();
Конструктори віртуальних базових класів запускаються до будь-яких конструкторів невіртуальних базових класів. Якщо ієрархія містить кілька віртуальних класів, то їхні конструктори викликаються в послідовності оголошення віртуальних базових класів. Після конструкторів віртуальних класів викликаються конструктори невіртуальних класів:
class X: public Y, virtual public Z {...…};
Послідовність виклику конструкторів: Z(); Y(); X();
Якщо віртуальний клас є похідним від невіртуального, то спочатку повинен бути запущений конструктор цього невіртуального базового класу.
Коли ієрархія містить множинне входження віртуального класу, то об'єкт даного класу конструюється тільки один раз. Однак, якщо є віртуальне й невіртуальне входження класу, то конструктор викликається один раз для всіх віртуальних входжень і один раз для всіх невіртуальних входжень даного класу.
Деструктори викликаються в послідовності, зворотній конструкторам.
Нижче показаний приклад, що відображає правила виклику конструкторів і деструкторів:
class B;
class B2;
class L1: public B2, virtual public B;
class L2: public B2, virtual public B;
class L3: public L1, virtual public L2;
void main() { L3 l; }
Послідовність виклику конструкторів:
B(); B2(); L2(); B2(); L1(); L3()
Послідовність виклику деструкторів:
~L3();~L1();~B2();~L2();~B2();~B().
