КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Віртуальні методи і поліморфізм. Конструктор
Віртуальний (що здається, гіпотетичний) метод має специфікатор (стандартну директиву) Virtual. Наприклад: Procedure Met2; Virtual; Віртуальний метод призначений для перевизначення віртуального методу попереднього предка. Неприпустимо змішування статичних і віртуальних методів при їх перевизначені. Обмеження: перевизначені віртуальні методи повинні мати такий самий набір формальних параметрів, як і найперший віртуальний метод багаторівневої ієрархії об'єктів.
Відповідно до цього основні відмінності перевизначення віртуальних методів від перевизначення статичних методів полягають в наступному: 1) якщо для екземпляра нащадка методи предка викликають інші віртуальні
2) віртуальні методи використовують пізнє пов'язання даних з методами, Компілятор не встановлює зв'язку об'єкту з віртуальним методом. Замість цього він створює спеціальну таблицю віртуальних методів (ТВМ, VMT -virtual Method Table). Для кожного типу об'єкту створюється своя ТВМ; кожен екземпляр об'єкту використовує цю ТВМ, єдину для даного типу віртуальних об'єктів. У кожній ТВМ міститься розмір даного типу об'єкту в байтах. ТВМ будь-якого об'єкту доступна через прихований параметр Self, що містить адресу ТВМ, яка передається методу при виклику. Скріплення кожного екземпляра об'єкту і його ТВМ здійснюється за допомогою конструктора на етапі виконання програми. Це спеціальний метод, подібний до звичайної процедури, але в заголовку замість PROCEDURE міститься слово CONSTRUCTOR.
Якщо об'єктний тип містить віртуальний метод, то він повинен містити хоч би один конструктор. Кожен екземпляр об'єкту повинен ініціалізуватися окремим викликом конструктора. Конструктор ініціалізував екземпляр об'єкту і встановлює для нього значення адреси його ТВМ. Екземпляр об'єкту містить тільки адресу ТВМ, а не саму ТВМ. Виклик конструктора повинен передувати виклику будь-якого віртуального методу для обробки даного екземпляра об'єкту. Звернення до віртуального методу до виклику конструктора викличе помилку на етапі виконання програми, оскільки немає зв'язку екземпляра об'єкту з його ТВМ.
При відладці програми можна використовувати директиву компілятора {$R+}. При цьому компілятор перевірятиме, чи ініціалізував екземпляр об'єкт, що викликає віртуальний метод. Якщо в процесі перевірки ініціалізації екземпляра об'єкту, що викликає віртуальний метод, буде виявлений виклик методу до ініціалізації об'єкту конструктором, видається повідомлення про фатальну помилку 210: Object not initialized - об'єкт не ініціалізував. Оскільки директива {$R+} уповільнює виконання програми, після відладки директиву треба видалити; за умовчанням працює директива {$R->. У об'єкті може бути скільки завгодно конструкторів. Конструктор не може бути віртуальним. Конструктор може бути тільки статичним і може бути перевизначений. Конструктори успадковуються так само, як і інші статичні методи. З конструктора можна викликати і віртуальні методи.
Лістинг 2. Використання віртуальних методів. Program virt1; {$F+,R+} Uses Crt; Type ObjName1 = object { - оголошення об'єкту-предка } Fl1: integer; Constructor Met1; { - конструктор } Procedure Met2; Virtual; { - віртуальний метод } End; ObjName2 = object(ObjName1) {- оголошення нащадка} Procedure Met2; Virtual; { - віртуальний метод } End; { --------- Методи об'єкту Objname1 ------------------------------- } Constructor ObjName1.Met1; Begin Fl1:= 12; Met2; { - виклик Met2 з конструктора } End; Procedure ObjNamel.Met2; Begin Writeln ( ' Працює метод ObjName1.Met2: FL1 = ', Fl1) End; {-----------------Методи об'єкту Objname2-------------------------------------------} Procedure ObjName2.Met2; Begin Fl1:= 34; Writeln ( ' Працює метод ObjName2.Met2: FL1 = ', Fl1) End; Var V1:ObjName1; {- змінна об'єктного типу - предка } V2: ObjName2; { - " " " нащадка }
{ ----------------- Основна програма--------------------------------------- } Begin ClrScr; Assign (Output, '2virt.res'); Rewrite (Output); Writeln ( ' ОБ'ЄКТИ, ВІРТУАЛЬНІ МЕТОДИ'); Writeln ( ' Працюємо з VI - екземпляром типу предка'); V1.Met1; { - викликається конструктор Met1 для екземпляра VI - предка } { Met1 викликає метод Objname1.Met2 - предка } V1.Met2; { - безпосередньо викликається метод Objname1.Met2; } Writeln ( ' Працюємо з V2 - екземпляром типу нащадка'); V2.Met1; { - викликається конструктор Met1 для екземпляра V2 - нащадка VI; Met1 викликає метод Objname2.Met2 - нащадка -в цьому гідність віртуальних методів } V2.Met2 { - безпосередньо викликається метод Objname2.Met2; } Close. (Output); End. Кожен екземпляр об'єкту повинен ініціалізуватися окремим викликом конструктора. Не можна ініціалізувати один екземпляр об'єкту і потім привласнювати цей екземпляр іншим, неініціалізованим об'єктам. Інші екземпляри, навіть якщо вони містять правильні дані, не ініціалізують оператором привласнення і заблокують систему при будь-яких викликах їх віртуальних методів. Наприклад: Var Obj1, Obj2: Tobj; { - оголошення змінних } Begin Obj1.Init; { - ініціалізація Obj1 } Obj2:= Obj1; { - неприпустимо до ініціалізації Obj2 за допомогою Obj2.Init; } End.
Додаткова можливість виклику методу, безпосередньо успадкованого об'єктом-нащадком, - використання ключового слова Inherited (успадкований) перед ім'ям методу, що викликається. Наприклад, Obj1 безпосередній предок об'єкту Obj2. До складу Obj1 входить метод Met1. Виклик цього методу об'єкту Obj1 з методу Obj2.Met2 може бути заданий явно у вигляді: Procedure Obj2.Met2; Begin Inherited Met1 (A1, A2); { Це еквівалентно виклику: Obj1.Met1 (A1, A2); } End; При цьому не треба знати ім'я об'єкту-предка (Obj1). Основні правила використання віртуальних методів: 1) якщо тип об'єкту-предка описує метод як віртуальний, то всі його нащадки, які реалізують свій метод з тим же ім'ям, повинні описати
Error 149: VIRTUAL expected - ОЧІКУЄТЬСЯ СЛОВО VIRTUAL. 2) якщо перевизначається віртуальний метод, то заголовок перевизначуваного
3) у описі об'єкту, що має віртуальні методи, обов'язковий - конструктор. Він встановлює роботу механізму віртуальних методів. Виклик віртуального методу без попереднього виклику конструктора може привести до тупикового стану. Щоб уникнути цього, на період відладки треба включити директиву компілятора {$R+}; 4) кожен екземпляр об'єкту повинен ініціалізуватися окремим викликом конструктора; 5) кількість конструкторів може бути будь-яким; 6) конструктор повинен бути статичним і може бути перевизначений.
Дата добавления: 2014-01-04; Просмотров: 720; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |