Студопедия
Новини освіти і науки:
МАРК РЕГНЕРУС ДОСЛІДЖЕННЯ: Наскільки відрізняються діти, які виросли в одностатевих союзах


РЕЗОЛЮЦІЯ: Громадського обговорення навчальної програми статевого виховання


ЧОМУ ФОНД ОЛЕНИ ПІНЧУК І МОЗ УКРАЇНИ ПРОПАГУЮТЬ "СЕКСУАЛЬНІ УРОКИ"


ЕКЗИСТЕНЦІЙНО-ПСИХОЛОГІЧНІ ОСНОВИ ПОРУШЕННЯ СТАТЕВОЇ ІДЕНТИЧНОСТІ ПІДЛІТКІВ


Батьківський, громадянський рух в Україні закликає МОН зупинити тотальну сексуалізацію дітей і підлітків


Відкрите звернення Міністру освіти й науки України - Гриневич Лілії Михайлівні


Представництво українського жіноцтва в ООН: низький рівень культури спілкування в соціальних мережах


Гендерна антидискримінаційна експертиза може зробити нас моральними рабами


ЛІВИЙ МАРКСИЗМ У НОВИХ ПІДРУЧНИКАХ ДЛЯ ШКОЛЯРІВ


ВІДКРИТА ЗАЯВА на підтримку позиції Ганни Турчинової та права кожної людини на свободу думки, світогляду та вираження поглядів



Приклад

Type

Begin

Begin

КЛЮЧОВЕ СЛОВО INHERITED ______________________________________________________

VAR

P1: ^Integer;

P2: ^String;

Простий спосіб розміщення таких динамічних об'єктів:

New ( P1 ); New ( Р2 ); ...

де P1 і Р2 - імена вказівників на динамічні об'єкти.

Begin

New(P1);

New(P2);

….

End;

В цьому прикладі після виконання команди New(P1)вказівник Р1 дістає значення рівне тому, яке досі мав вказівник HeapPtr, а значення вказівника HeapPtrбуде збільшене на 2, оскільки довжина внутрішнього представлення типу INTEGER, з яким зв’язаний вказівник Р1, дорівнює 2 байти. Оператор New(P2) викликає виділення блоку пам’яті довжиною 256 байтів і зміщення вказівника HeapPtr на цю ж величину вгору. Якщо вказівник посилається на тип даних, для якого потрібно пам’яті більше, аніж доступно для розподілу в Heap-області, то в цьому випадку відбувається помилка виконання програми. Процедура New може бути використана в якості функції, що повертає вказівник конкретного типу даних. Наприклад, якщо змінна P1 має тип даних, визначений як ^Integer, а змінна P1Int – тип даних Р1, то наступні два оператори New(P1Int); P1Int:=New(P1); еквівалентні. Після того, як вказівник здобув якесь значення, тобто став вказувати на конкретний фізичний байт пам’яті, то за цією адресою можна розмістити будь-яке значення відповідного типу даних VAR P1,P2:^Integer; …. Begin New(P1); New(P2); P1^:=7; P1^:=7*4; End.
     

New може використовуватися також як функція, яка повертає значення вказівника.

Наприклад:

P1 := New ( Pobjname );

де Pobjname - ім'я типу вказівника динамічного об'єкту.

Звернення до змінної - екземпляру об'єкту за допомогою вказівника проводиться у вигляді Р1^ або Р2^.

Виклики методів проводяться звичайним способом.

Наприклад: Р1^.МЕТ2;

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

Наприклад: P1^.INIT; P2^.INIT;

Якщо конструктор не може розмістити динамічний об'єкт ОП, то він повертає "порожній" вказівник, наприклад: P1 = NIL.

Для роботи з динамічними об'єктами, що містять віртуальні методи, Паскаль має процедури NEW і DISPOSE з розширеними можливостями. Розширений синтаксис процедури Newдозволяє виділяти з купи ОП для об'єкту і ініціалізувати сам об'єкт за допомогою виклику його конструктора. Для цього процедура New викликається з двома параметрами: ім'ям вказівника і ім'ям конструктора.

Наприклад: New (P1,init); New(P2,init);.

Параметр INIT виконує виклик конструктора і ініціалізацію динамічного об'єкту.

Для роботи з нетипізованими вказівниками можна використовувати процеду­ри GetMem і FreeMem.

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

Виклик процедури GetMem має такий синтаксис:

GetMem (<ідентифікатор вказівника>,<обсяг пам'яті>);

Тут <ідентифікатор вказівника> - змінна типу pointer;

<обсяг пам'яті> — змінна або вираз типу word.

Обсяг пам'яті задається в байтах. Обсяг пам'яті, що виділяється для однієї динамічної змінної, не може перевищувати 65 521 байт.

Крім того, не можна виділяти ділянок пам'яті, довжина яких перевищує довжину найбільшої вільної ділянки в купі, що її повертає функція MaxAvail. Тому для забезпечення коректності роботи процедури GetMem бажано перед її викликом перевіряти наяв­ність достатньо великої вільної ділянки пам'яті if MaxAvail>9999 then GetMem(ptr.10000) else Write(‘No sufficient memory');
     

Зазначимо, що загальний обсяг усіх вільних ділянок динамічної пам'яті об­числює функція MemAvail.

 

В попередньому прикладі ми використовували виклик предківського методу шляхом вказання імені предка, після якого пишеться крапка та ім’я конструктора.

constructor TStudent1.init(nm,dt:string;rt,bl:real);

IF NOT TStudent.Init(nm,dt,rt) THEN Failed;

bal:=bl;

end;

Pascal дає можливість використовувати спеціальне слово INHERITED , використовуючи яке можна викликати методи предка без вказання імені предка.

constructor TStudent1.init(nm,dt:string;rt,bl:real);

IF NOT INHERITED Init(nm,dt,rt) THEN Failed;

bal:=bl;

end;

Це може виявитися корисним при використанні великої ієрархії об’єктів, коли складно запам’ятати всі зв’язки типу «предок-потомок».

3. ВИДАЛЕННЯ ДИНАМІЧНИХ ОБ’ЄКТІВ. ______________________________________________

Динамічними можуть бути об'єкти із статичними і віртуальними методами. Видалення динамічних об'єктів може бути за допомогою процедур Dispose або за допомогою деструктора.

Синтаксис виклику процедури Dispose такий:

Dispose (<ідентифікатор вказівника>);

Подібно до інших динамічних типів даних динамічні об'єкти із статичними методами можуть видалятися за допомогою Dispose.

Наприклад: Dispose ( P1 );

Приклад програми з динамічним об'єктом із статичними методами даний в лістингу 1.

Для звільнення ОП динамічних об'єктів з віртуальними методами використовуються особливі методи - деструктори. В якості їх імені рекомендується вживати ім'я Done. Вони призначені для виконання завершуючих дій програми. Деструктори розміщуються разом з іншими методами об'єкту у визначенні типу і оформляється так само, як звичайний метод-процедура, але слово PROCEDURE замінюється словом DESTRUCTOR.

Наприклад: Destructor Tobjl.Done;

Виклик деструкції (Done) поза процедурою Dispose не приведе до автоматичного звільнення ОП, займаною екземпляром об'єкту, тобто неприпустимо Р1^.Done;.

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

Він має 2 параметри: ім'я покажчика на об'єкт і ім'я деструкції.

Наприклад: Dispose ( P1,done);

де Done - ім'я деструкції об'єкту, на який указує Р1.

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

TStudent=object

Name:String[30];

Date:string[10];

rate:real;

constructor init(nm,Dt:String;rt:real);

destructor done; virtual;

function GetName:string; virtual;

function getdate:string;

function getrate:real;

procedure showname;

procedure showdate;

procedure showrate;

end;

Деструктори можна успадковувати і вони можуть бути статичними чи віртуальними. Оскільки різні програми завершення об’єктів звичайно вимагають різних типів об’єктів, рекомендується завжди визначати деструктори віртуальними, щоб для кожного типу об’єктів виконувався правильний деструктор.

Деструкція виконується як звичайний метод. Коли буде виконано останню його дію, якщо об'єкт містить віртуальні методи, то деструктор проводить пошук розміру об'єкту в ТВМ і передає його процедурі Dispose, яка і звільняє правильну кількість байт, незалежно від того, чи вказував Р1 на тип предка або нащадка.
     

Метод деструкції може бути і порожнім, оскільки основна інформація міститься не в тілі деструкції, а пов'язана з його заголовком, що містить слово Destructor.

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

Наприклад:

Destructor Tobj1.Done;

Begin

. . . INHERITED Done;

End;

Для коректного звільнення ОП при використанні поліморфних об'єктів також треба використовувати процедуру Dispose розширеного вигляду.

Поліморфним є об'єкт, значенням якого можуть бути екземпляри різних (таких же або породжених) типів. Ці правила відносяться і до вказівників на об'єкти: об'єкт, що адресується ними, також буде поліморфним.

Термін "поліморфний" означає, що компілятор, будуючи код об'єкту, під час компіляції, "не знає", який тип об'єкту буде насправді використаний. Єдине, що він "знає", - це те, що об'єкт належить ієрархії об'єктів, що є нащадками вказаного типу предка. Розміри різних об'єктів ієрархії можуть бути різні. Інформація про розмір об'єкту, що видаляється, стає доступною, для деструкції з ТВМ у момент видалення екземпляра об'єкту. ТВМ будь-якого об'єкту доступна через параметр Self, що містить адресу ТВМ, яка передається деструкції при його виклику.

Деструкція може об'єднувати видалення об'єкту з іншими діями, необхідними для коректного видалення. Наприклад, при видаленні динамічного об'єкту може знадобитися не тільки звільнення займаною ним ОП. Об'єкт може містити вказівник на динамічні об'єкти або зв'язані структури (стеки, черги, списки), які треба видалити в певному порядку. Всі операції для видалення динамічного об'єкту повинні об'єднуватися в один метод, щоб об'єкт міг бути знищений за допомогою одного виклику. Наприклад: Objl .Done; або Dispose ( Pi, Done ); Для одного і того ж типу об'єкту може бути декілька деструкцій. Деструкції можна успадковувати. Вони можуть бути статичними або віртуальними. Наприклад: Destructor Done; Virtual; Для динамічних об'єктів доцільно оголошувати віртуальну деструкцію, навіть якщо об'єкт не містить інших віртуальних методів. Якщо деструкція віртуальна, зв'язок з конкретним екземпляром об'єкту здійснюється в процесі виконання програми. Отже, залежно від типу екземпляра об'єкту деструкція звертатиметься до ТВМ-предка або до ТВМ-потомка ієрархії об'єктів. Розміри що виділяється для них ОП можуть бути різними. При цьому для кожного типу об'єкту виконується деструкція, відповідна даному типу об'єкту. Деструктори працюють з динамічними об'єктами. Але застосування деструкторів до статичних об'єктів не є помилкою і не приведе до некоректної роботи програми.
     

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

Наведемо синтаксис виклику процедури:

FreeMem(<ідентифікатор вказівника>,<обсяг пам'яті>);
Слід пам'ятати, що розподіл динамічної пам'яті за допомогою процедури GetMem потребує її звільнення за допомогою процедури FreeMem. Під час застосування цих процедур до одного й того самого вказівника значення параметрів, що задають обсяг динамічної пам'яті, мають збігатися.
     

У результаті багатьох викликів процедур New і Dispose, а також GetMem і FreeMem динамічна пам'ять фрагментується. В ній з'являються несуміжні вільні ділянки. Щоб мати можливість звільняти динамічну пам'ять, використовуються процеду­ри Mark і Release.

Синтаксис виклику цих процедур такий:

Mark(<ідентифікатор вказівника>); Release(<ідентифікатор вказівника>);

Процедура Mark запам'ятовує поточне значення вказівника HeapPtr у вказівнику, що є параметром процедури.

Нагадаємо, що вказівник HeapPtr містить адресу по­чатку вільної динамічної пам'яті.
     

Процедура Release звільняє динамічну пам'ять, починаючи від комірки, що адресується параметром процедури, до кінця динаміч­ної пам'яті. Один виклик процедури Releaseзнищує список усіх вільних фрагмен­тів у динамічній пам'яті, створених викликами процедури Dispose, а також усі дина­мічні змінні, створені після виклику процедури Mark.

Використовувати два різні механізми звільнення динамічної пам'яті (за допомогою процедур Dіspose і Release) в межах однієї програми небажано, оскільки доведеться стежити за тим, щоб про­цедура Dispose не звільняла змінні, що вже були звільнені процедурою Release.
     

Constructor - для віртуальних методів, для створення ТВМ при використанні статичних і динамічних об'єктів.

Destructor - для звільнення ОП динамічних об'єктів, що містять віртуальні методи.

Лістинг 1. Динамічні об'єкти із статичними методами.

Program novirt;

Uses Crt; { Оголошення: }

Type Objname1 = object { - об'єкту-предка }

Fl1 : integer;

Procedure Met1;

Procedure Met2;

End;

Objname2 = object ( Objname1 ) { - об'єкту-нащадка }

Procedure Met2; End;

Pobjname1 = ^ObjName1; {- тип - покажчик на об'єкт Objname1 }

Pobjname2 = ^ObjName2; { - " " " " Objname2 }

{ ----------------------------- Методи об'єкту Objname1-------------------------- }

Procedure Objname1.Met1;

Begin

Met2; { - виклик тільки методу Objname1.Met2 !!}

End;

Procedure Objname1.Met2;

Begin

Fl1 := 12;

Writeln ( 'Працює метод Objname1.Met2: Fl1 = ', Fl1)

End;

{----------------------- Методи об'єкту Objname2-----------------------------------}

Procedure Objname2.Met2;

Begin

Fl1 := 34;

Writeln ( 'Працює метод Objname2.Met2: Fl1 = ', Fl1)

End;

Var V1 : Pobjname1; { - динамічний об'єкт V1 }

V2 : Pobjname2; { - " " V2 }

{------------------------------ Основна програма -----------------------------------}

Begin

Clrscr;

Assign (Output, 'dnovirt.res'); Rewrite (output);

Writeln ('ДИНАМІЧНІ ОБ'ЄКТИ, СТАТИЧНІ МЕТОДИ');

Writeln ('Працюємо з VI - екземпляром типу предка');

New ( V1 ); { - створення динамічного об'єкту V1 }

V1^.Met1; { - виклик методу Objname1 .Met1; }

Vl1.Met2; { - " " Objname1.Met2; }

Dispose ( V1 ); { - видалення об'єкту V1 }

Writeln ('Працюємо з V2 - екземпляром типу нащадка');

New ( V2 ); { - створення динамічного об'єкту V2 }

V2^.Met1; { - викликає ЗАВЖДИ метод Objname1.Met2, а не Objname2.Met2 }

V2^.Met2; { - виклик методу Objname2.Met2; }

Dispose ( V2 ); { - видалення об'єкту V2 }

Close (Output);

End.

Програма ех_2 демонструє механізм роботи процедур New і Dispose, а також Mark і Release. Стан динамічної пам'яті під час роботи програми показано на рисунку.

program ex_2;

var

ptr,p1,р2,р3,р4:^іnteger;

begin

New(p1); {виділити пам'ять для цілого числа }

Mark(ptr); {запам'ятати адресу початку вільної області}

New(p2); {виділити пам'ять ще для трьох цілих чисел }

New(p3);

New(p4);

Dispose(p3); {звільнити пам'ять від рЗ^ }

Release(ptr); {звільнити пам'ять від р2^,рЗ^, р4^ }

{ Dispose(p4); {помилка: змінну р4^ вже видалено!!! }

readln;

end.

Приклад програми з динамічним об'єктом з віртуальними методами і з використанням деструкції

Лістинг 2. Динамічні об'єкти з віртуальним методом.

Program Dvirt;

{$F+,R+}

Uses Crt;

Type Objname1 = object { - тип об'єкту-предка }

Fl1 : integer;

Constructor Met1; {- конструктор типу Objname1 }

Destructor Done; Virtual; {- деструкція типу Objname1 }

Procedure Met2; Virtual;

End;

Objname2=object (Objname1) {- тип нащадка Objname1 )

Procedure Met2; Virtual;

Destructor Done; Virtual; {- деструктор типу Objname2 }

End;

Pobjname1 = ^ObjName1; {- тип - покажчик на об'єкт Objname1}

Pobjname2 = ^ObjName2; { -" " " Objname2 }

{---------------------------- Методи об'єкту Objname1---------------------------------------}

Constructor Objname1.Met1;

Begin

Met2; {- виклик Met2 з конструктора }

End;

Destructor Objname1.Done;

Begin

Writeln ('Звільняється ОП об'єкту типу Objname1');

End;

Procedure Objnamel.Met2;

Begin

Fl1 := 12;

Writeln ('Працює метод Objname1.Met2: Fl1= ', Fl1)

End;

{ Методи об'єкту Objname2 }

Procedure Objname2.Met2;

Begin

Fl1 := 34;

Writeln ('Працює метод Objname2.Met2: Fl1 = ', Fl1)

End;

Destructor Objname2.Done; Begin

Writeln ('Звільняється ОП об'єкту типу Objname2');

End;

Var V1 : Pobjname1; { - динамічний об'єкт V1 }

V2 : Pobjname2; { - " " V2 }

{ Основна програма

Begin

Clrscr;

Assign (Output, 'Dvirt.res');

Rewrite (output);

Writeln ('ДИНАМІЧНІ ОБ'ЄКТИ, ВІРТУАЛЬНІ МЕТОДИ' );

Writeln ('Працюємо з V1 - екземпляром типу предка');

{ Викликається конструктор Met1 для екземпляра V1 - предка:}

New (V1,met1); {- створення динамічного об'єкту V1 }

V1^.Met2; {- виклик методу Objname1.Met2; }

{ Видалення об'єкту - тільки за допомогою Dispose і Done: }

Dispose (V1,done); {- видалення об'єкту V1 деструкцією Objname1.Done }

Writeln ('Працюємо з V2- екземпляром типу нащадка');

{ Викликається конструктор Met1 для екземпляра V2 - нащадка V1:}

New ( V2, Met1 ); { - створення динамічного об'єкту V2 }

V2^.Met2; {- виклик методу Objname2 .Met2; }

{ Видалення об'єкту - тільки за допомогою Dispose і Done: }

Dispose (V2,done); { - видалення об'єкту V2 деструкцією Objname2.Done}

Close (Output);

End.


Читайте також:

  1. Абсолютні синоніми (наприклад, власне мовні й запозичені) в одному тексті ділового стилю вживати не рекомендується.
  2. Алгоритм однофакторного дисперсійного аналізу за Фішером. Приклад
  3. Базові та прикладні класифікації
  4. В чому полягає явище тунелювання через потенціальний бар’єр, наведіть приклади.
  5. Визначення і приклади
  6. Врахування витраті втрат електроенергії. Приклад складання електробалансу.
  7. Головною метою наукової діяльності в системі вищої освіти повинен стати розвиток фундаментальних та приклад­них досліджень.
  8. Деякі приклади застосування ППП
  9. Дієслова з префіксом дис-виражають значення ліквідації дії, названої безпрефіксним дієсловом, наприклад: гармонізувати – дисгармонізувати, асоціювати – дисасоціювати.
  10. Для одиничного і дрібносерійного виробництва норма витрати визначається як укрупнена, наприклад, на 1000 станко-годин роботи даного виду роботи устаткування
  11. Додаток И - Приклад виконання ремонтного креслення деталі
  12. Етикет – (прикріплювати) установлений порядок поведінки в товаристві, певному оточенні, наприклад, придворний етикет, дипломатичний етикет.




Переглядів: 572

<== попередня сторінка | наступна сторінка ==>
Показник виробничого фінансового лівериджу | Нестатутні джерела

Не знайшли потрібну інформацію? Скористайтесь пошуком google:

  

© studopedia.com.ua При використанні або копіюванні матеріалів пряме посилання на сайт обов'язкове.


Генерація сторінки за: 0.043 сек.