- •Історична довідка
- •Характеристика й особливості мови
- •Алфавіт мови
- •Службові (зарезервовані) слова.
- •Структура програми мови Turbo Pascal
- •Розділ оголошень і угод
- •Розділ текстів процедур і функцій
- •Розділ основного блоку програми
- •Процедури введення-виведення. Деякі вбудовані функції Турбо-Паскаля.
- •Функції числових параметрів.
- •Базові управляючі конструкції Турбо-Паскаля Оператори умовного переходу.
- •1. Оператор if.
- •2. Оператор вибору (case)
- •Оператори циклів у Паскалі
- •1. Цикл із післяумовою (Repeat)
- •2. Цикл із предумовою (While)
- •3. Цикл із лічильником або параметром (For)
- •Концепція типів даних. Типи даних в мові Pascal
- •Дійсні типи
- •Бульовий (логічний) тип
- •Символьні і рядкові змінні
- •1. Символьний тип
- •2. Рядковий тип
- •Перерахований та обмежений типи
- •1. Перерахований тип
- •2. Обмежений тип
- •1. Поняття масиву. Одномірні масиви
- •2. Багатомірні масиви
- •3. Сортування і пошук
- •Множинний тип
- •Тип запис
- •Процедури і функції
- •Формальні і фактичні параметри. Механізм параметрів
- •Параметри - значення
- •Параметри-змінні
- •Безтипові параметри
- •Приведення типів.
- •Процедурні типи
- •Рекурсія Рекурсивні визначення
- •Рекурсивні підпрограми
- •Алгоритми з поверненням. Розв’язок задачі про рух коня
- •Алгоритми з поверненням. Розв’язок задачі про вісьмох ферзів
- •If підходить тнеn
- •Модулі в Турбо Паскалі
- •Модуль crt
- •1. Керування екраном
- •2. Робота з клавіатурою
- •3. Інші можливості
- •Графіка в Турбо Паскалі
- •1. Включення і вимикання графічного режиму.
- •2. Побудова елементарних зображень
- •3. Виведення текстової інформації.
- •Файли в мові програмування Pascal
- •Установчі і завершальні операції
- •Операції введення-виведення
- •Обробка помилок введення-виведення
- •Переміщення по файлу
- •Спеціальні операції
- •Текстові файли
- •1. Оголошення файлової змінної і прив'язка до файлу на диску
- •2. Читання даних з файлу
- •3. Запис даних у файл
- •Двійкові файли
- •1. Типізовані файли
- •2. Нетипізовані файли
- •Статичні і динамічні змінні
- •Покажчики
- •Стан покажчика
- •Установка розмірів динамічної пам'яті
- •Сумісність і перетворення посилкових типів
- •Динамічні структури даних
- •Динамічні змінні: інші види списків, стек і черга.
- •1. Інші види списків
- •2. Стек і черга
- •Дерева і пошук у деревах
- •1. Визначення й описи структур даних
- •1. Масив
- •2. Список
- •3. Дерево
- •2. Алгоритми
- •1. Лінійний пошук у масиві
- •2. Двійковий пошук
- •3. Лінійний пошук у списку
- •Змішані таблиці
- •Об’єктно-орієнтоване програмування. Що таке об’єктно-орієнтоване програмування
- •Інкапсуляція
- •Спадкування
- •Віртуальні методи і поліморфізм
- •Конструктори, динамічні об'єкти і деструктори
- •Поля і методи: сховані і загальнодоступні
- •Системно- залежні розширення
- •Налагодження змінних
- •Оверлеї
- •Переривання і системні виклики
- •Доступ до пам'яті і портів
- •Перевизначення переривань
Конструктори, динамічні об'єкти і деструктори
Якщо в об'єктному типі є хоча б один віртуальний метод, у ньому повинний бути і спеціальний метод, відомий як конструктор, який обов’язково повинний бути застосований до екземпляра об'єкта до першого звертання до віртуального методу. У силу цього конструктор звичайно являє собою метод, що задає для об'єкта деякі початкові значення (тобто виконуючий його ініціалізацію). Конструктор може бути визначений або в даному об'єкті, або успадкований від об'єкта-предка. При цьому сам конструктор віртуальним методом бути не може.
В описі об'єктного типу заголовок конструктора відрізняється від заголовка звичайного методу тільки тим, що в ньому зарезервоване слово PROCEDURE замінене на CONSTRUCTOR. Чим реально конструктор відрізняється від звичайного методу? Конструктор, крім описаних у ньому дій, установлює зв'язок між об'єктом і спеціальною таблицею віртуальних методів, що містить адреси кодів, які реалізують віртуальні методи.
Як уже відзначалося в цій главі вище, екземпляри об'єктних типів можуть визначатися як статичні (у розділі описів змінних) і як динамічні, причому останнє має місце найчастіше. От як можна створити динамічні екземпляри об'єктів Dotl і Rlngl:
var
Dotl : ^Dot
Ringl : ^Ring; begin
New(Dotl, lnit);
New(Ringl, Init);
Вище згадувалося, що якщо в об'єкті маються віртуальні методи, перед звертанням до них екземпляр даного об'єкта повинний викликати конструктор. Саме таким конструктором тут є Init, що викликається процедурою New (як свій другий параметр, використовуючи при цьому розширений синтаксис). (Приклад програми, у якій екземпляри об'єктів Dotl і Ringl оголошені в якості динамічних, мається наприкінці даного розділу.)
Після завершення роботи з динамічним об'єктом виділену для нього пам'ять варто звільнити. Це виконується за допомогою стандартної процедури DISPOSE:
Dispose (Dotl, Done);
Dispose (Ringl, Done);
Тут процедура DISPOSE звертається до деструктора DONE, що зазначений у якості її другого параметра. В описі об'єктного типу заголовок деструктора відрізняється від заголовка звичайного методу тільки тим, що в ньому зарезервоване слово PROCEDURE замінене на DESTRUCTOR. Однак, на відміну від конструктора, зарезервоване слово DESTRUCTOR є синонімом PROCEDURE. Іншими словами, метод, що завершує роботу з об'єктом, оформляється спеціальним зарезервованим словом тільки для того, щоб дотримати стилістичної симетрії (якщо є спеціальний починаючий метод, логіка диктує, що повинено бути і відповідний завершальний метод). Крім того, на відміну від конструкторів, деструктори можуть являти собою віртуальні методи. При цьому необхідно розуміти що виклик деструктора Done не як параметр процедури Dispose, а самого по собі, динамічну пам'ять не звільнить.На закінчення приведемо текст програми, аналогічної попередній, у якій об'єкти Dotl і Ringl оголошені в якості динамічних.
program ObjDotCircl;
uses crt, graph;
type Dot=object
a, b :integer;
constructor Init (x,y:integer);
procedure Show; virtual;
procedure Hide; virtual;
procedure Move (Da, Db: integer);
destructor Done;
end;
Ring = object (Dot) ;
Rad : integer;
constructor Init (x, y, z : integer);
procedure Show; virtual;
procedure Hide; virtual;
destructor Done;
end;
constructor Dot.Init;
begin
a:=x;
b:=y;
end;
procedure Dot.Show;
begin
PutPixel(a,b,White);
end;
procedure Dot.Hide;
begin
PutPixel(a,b,0);
end;
procedure Dot.Move;
begin
Hide;
a:=a+Da; b:=b+Db;
Show
end;
constructor Ring.Init;
begin
a:=x;
b:=y;
Rad:=z;
end;
procedure Ring.Show;
begin
SetColor(Black);
Circle(a,b,Rad);
end;
procedure Ring.Hide;
begin
SetColor(0);
Circle{a,b,Rad);
end;
destructor Dot.Done;
begin
Hide;
end;
destructor Ring.Done;
begin
Hide;
end;
var i,j,k,Err:integer;
a:char;
Dotl:^Dot; Ringl:^Ring;
begin {тіло програми}
i:=detect;
initgraph(i,j,");
Err:=GraphResult;
If Err <> grOK then WriteLn (GraphErrorMsg( Err))
else
begin
New(Dotl,Init(GetMaxX div 2, GetMaxY div 2))
Dotl^.Show;
New(Ringl,Init(GetMaxX div 2, GetMaxY div 2, GetMaxY div 6));
Ringl^.Show;
while KeyPressed do
a:=ReadKey;
repeat
begin
a:=ReadKey;
case ord(a) of
72:Dotl^.Move(0,-5);
80:Dotl^.Move(0,5);
77:Dotl^.Move(5,0);
75:Dotl^.Move(-5,0);
73:Ringl^.Move(0,-5);
81:Ringl^.Move(0,5);
79:Ringr.Move(5,0);
71:Ringl^.Move(-5,0); end;
end;
until a = chr(27);
Dispose (Dotl, Done);
Dispose(Ringl,Done)
end;
end.
У яких випадках має сенс використовувати динамічні змінні, ми з'ясували при вивченні покажчиків і використання динамічної пам'яті. Наприклад, якщо програма оперує множиною об'єктів (а не всього двома, як у нашому випадку) і звичайної (чи статичної) пам'яті для всіх цих об'єктів не вистачає, варто помістити їх у динамічну пам'ять. Крім того, якщо використання об'єкта починається в середині програми чи завершується задовго до її кінця, щоб не займати пам'ять увесь час, також доцільно оголосити такі об'єкти в якості динамічних. (Останнє для нашого приклада також не актуально, оскільки екземпляри об'єктів тут використовуються від початку і до кінця; тобто строго говорячи, пам'ять за допомогою деструкторів у нашій програмі можна було б і не звільняти.)