русс | укр

Мови програмуванняВідео уроки php mysqlПаскальСіАсемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование


Linux Unix Алгоритмічні мови Архітектура мікроконтролерів Введення в розробку розподілених інформаційних систем Дискретна математика Інформаційне обслуговування користувачів Інформація та моделювання в управлінні виробництвом Комп'ютерна графіка Лекції


Виявлення помилок конструктора


Дата додавання: 2014-04-22; переглядів: 920.


Pascal дозволяє встановити функцію користувача обробки помилок динамічної пам’яті за допомогою змінної HeapError,що є стандартною і не потребує опису в розділі змінних. Вона містить адресу стандартної функції обробки помилок в Pascal-i, що може бути заміщена. Функція користувача обробки помилок повинна мати формат

Function HeapFunc(Size:Word):Integer; Far

Наявність директиви Far обов’язкова, вона сповіщає про те, що для функції, після якої вона розміщена, повинен використовуватися віддалений тип виклику.

Нова функція обробки помилок встановлюється шляхом присвоювання її адреси змінній HeapError таким способом:

HeapError:=@HeapFunc

Така можливість може виявитися корисною при використанні конструкторів.

За замовчуванням, якщо не вистачає пам’яті для розміщення екземпляру динамічного об’єкту, то виклик конструктора, який використовує розширений синтаксис процедури New, генерує фатальну помилку виконання з кодом 203. Якщо встановлюється функція користувача обробки помилок динамічної пам’яті, яка повертає 1, а не стандартний результат 0, то виклик конструктора через New буде повертати Nil в тому випадку, якщо конструктор не зможе завершити запит (замість припинення роботи програми).

Код, який виконує розміщення та ініціалізацію поля таблиці віртуальних методів динамічного екземпляра, є частиною коду, що розміщується безпосередньо після точки входу в конструктор. Якщо управління досягає початку операторної секції конструктора, екземпляр вже розміщений та ініціалізований. Якщо розміщення завершилося невдало, і якщо функція помилки динамічно розподіленої області пам’яті повернула 1, то конструктор пропускає виконання операторної секції і повертає вказівник Nil. Таким чином, вказівник, який заданий в розширеній процедурі New, що викликає конструктор, буде встановлений в Nil(це означає, що пам’ять не виділена).

Якщо управління передається в початок операторної секції конструктора, то це означає, що екземпляр об’єктного типу вже розміщений та ініціалізований. Однак сам конструктор може спробувати розмістити динамічну змінну, щоб ініціалізувати поле вказівника екземпляра, але ця спроба може виявитися невдалою. Якщо це відбулося, то коректно працюючий конструктор повинен відмінити попередньо здійснене виділення пам’яті і видалити вже розміщений екземпляр об’єктного типу, щоб кінцевим результатом операції виявився вказівник Nil.Щоб зробити можливою таку відміну, Pascal надає нову стандартну процедуру Fail, яка не має параметрів і може викликатися лише зсередини конструктора. Виклик Failзмушує конструктор видалити динамічний екземпляр, що був розміщений при вході в конструктор, і призводить до повернення вказівника Nil для індикації невдалої спроби.

Якщо динамічні екземпляри розміщуються за допомогою розширеного синтаксису New, то результуюче значення Nil, що передається вказівнику, свідчить про невдалу операцію. Але не існує таких змінних типу вказівник, які можна було б перевірити після створення статичного екземпляру чи після виклику успадкованого конструктора. Замість цього Pascal в якості функцій дозволяє використовувати конструктори, що повертають результат типу BOOLEAN. Повернуте значення TRUE означає успіх, а FALSE – невдачу завдяки виклику Fail всередині конструктора.

Розглянемо, як можна описати послідовний виклик конструкторів типу TStudent і TStudent1. Досі вони не давали можливості визначати помилки:

Constructor TStudent.init(nm,dt:string;rt:real);

begin

name:=nm;

date:=dt;

rate:=rt;

end;

 

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

begin

TStudent.Init(nm,dt,rt);

bal:=bl;

end;

 

При такому описі, якщо ініціалізується екземпляр дочірнього типу TStudent1, то він викликає конструктор типу TStudent. Якщо при виклику цього останнього трапиться помилка, доведеться відмінити і виклик першого конструктора.

От як можна переписати конструктор TStudent1.init з врахуванням виявлення помилок:

 

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

Begin

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

bal:=bl;

end;

Function HeapFunc(Size:Word):Integer;Far;

Begin

HeapFunc:=1;

End;

 

Зверніть увагу, що функція HeapFuncвиконує єдину операцію: при будь-якому виклику повертає 1. Виконувати інші операції в даному випадку немає потреби.

 


<== попередня лекція | наступна лекція ==>
Динамічні об’єкти і процедура New | Ключове слово INHERITED


Онлайн система числення Калькулятор онлайн звичайний Науковий калькулятор онлайн