русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

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

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Виртуальные методы


Дата добавления: 2015-06-12; просмотров: 843; Нарушение авторских прав


13.5.2.1. Виртуализация методов. Из правил совместимости фактических и формальных параметров типа «объект» следует, что в качестве фактического параметра может выступать объект любого производного типа от типа формального параметра. Таким образом, во время компиляции процедуры неизвестно, объект какого типа будет ей передан в качестве фактического параметра (такой параметр называется полиморфным объектом). В полной мере полиморфизм объектов и методов реализуется при помощи виртуальных методов.

Метод становится виртуальным, когда за его определением в типе объекта ставится служебное слово VIRTUAL:

PROCEDURE ИмяМетода( параметры ); VIRTUAL;

или

FUNCTION ИмяМетода( параметры ) : ТипЗначения; VIRTUAL;

При виртуализации методов должны выполняться следующие условия:

1. Если прародительский тип объекта описывает метод как виртуальный, то все его производные типы, которые реализуют метод с тем же именем, должны описать этот метод тоже как виртуальный. Другими словами, нельзя заменять виртуальный метод статическим. Если же это произойдет, компилятор сообщит об ошибке номер 149 VIRTUAL expected («Ожидается служебное слою VIRTUAL»).

2. Если переопределяется реализация виртуального метода, то заголовок заново определяемого виртуального метода в производном типе не может быть изменен. Иначе говоря, должны остаться неизменными порядок расположения, количество и типы формальных параметров в одноименных виртуальных методах. Если этот метод реализуется функцией, то не должен изменяться и тип результата. При изменении заголовка метода компилятор выдаст сообщение об ошибке номер 131 Header does not match previous definition («Заголовок не соответствует предыдущему определению»). {282}

3. В описании объекта должен обязательно описываться специальный метод, инициализирующий объект (обычно ему дают название Init). В этом методе служебное слово PROCEDURE в объявлении и реализации должно быть заменено на слово CONSTRUCTOR. Это служебное слово обозначает особый вид процедуры — конструктор, который выполняет установочную работу для механизма виртуальных методов. Все типы объектов, которые имеют хотя бы один виртуальный метод, должны иметь конструктор. Конструктор всегда вызывается до первого вызова виртуального метода. Вызов виртуального метода без предварительного вызова конструктора может привести систему к тупиковому состоянию, а компилятор не проверяет порядок вызовов методов. Помните об этом!



13.5.2.2. Конструкторы и таблица виртуальных методов. Каждый экземпляр (переменная) типа «объект», содержащий виртуальные методы, должен инициализироваться отдельным вызовом конструктора. Если переменная А инициализирована вызовом конструктора, а переменная В того же типа не инициализирована, то присваивание В:=А не инициализирует переменную В и при вызове ее виртуальных методов программа может «зависнуть».

Чтобы понять, что делает конструктор, разберемся в механизме реализации виртуальных методов. Каждый объектный тип (именно тип, а не экземпляр) имеет «таблицу виртуальных методов» (VMT), которая содержит размер типа объекта и адреса кодов процедур или функций, реализующих каждый из его виртуальных методов. При вызове виртуального метода каким-либо экземпляром местонахождение кода реализации этого метода определяется по таблице VMT для типа этого экземпляра. Конструктор же устанавливает связь между экземпляром, который вызывает конструктор, и таблицей виртуальных методов данного объектного типа. Если же конструктор не будет вызван до обращения к виртуальному методу, то перед компьютером станет вопрос, где же искать этот метод. Это и приведет к тупиковой ситуации.

Важно помнить, что таблица виртуальных методов — одна для каждого типа, а не у каждой переменной типа «объект». Переменная лишь держит связь с таблицей своего типа, и эта связь устанавливается конструктором. В объекте может быть определено несколько конструкторов. Сами конструкторы могут быть только статическими, хотя внутри конструктора могут вызываться и виртуальные методы.

При передаче в процедуру или функцию полиморфного объекта, имеющего виртуальные методы, адреса этих методов передаются {283} через соответствующую объекту таблицу VMT. Это гарантирует, что сработают именно те методы, которые подразумевались при объявлении типа объекта. Кроме того, если объект Z наследует от объекта Y виртуальный метод, вызывающий другие методы, то последние вызовы будут относиться к методам объекта Z, а не Y. В случае статических методов все было бы наоборот (вызовы не «вернулись» бы в Z).

Мы начали этот раздел с примера полиморфной процедуры (см. рис. 13.6). Чтобы она заработала, надо сделать некоторые методы виртуальными и объявить конструкторы в объектах. Это проделано на рис. 13.7.

USES CRT; { в примере используется системный модуль CRT } TYPE ObjPos = OBJECT Line : Word; { номер строки } Col : Word; { номер столбца } { ! } CONSTRUCTOR Init(init_line,init_col: Word); { ! } PROCEDURE Print; VIRTUAL { зарезервировано } END; CONSTRUCTOR ObjPos.Init( init_line, init_col : Word ); BEGIN Line := init_line; { метод задания номера строки } Col := init_col; { метод задания номера столбца } END; PROCEDURE ObjPos.Print; { пустая процедура вывода } BEGIN Write( #7 ); { это вызовет звуковой сигнал } END; TYPE ObjSym = OBJECT( ObjPos ) { объявление наследования } Sym : Char; { поле-значение символа } { ! }CONSTRUCTOR Init(init_line,init_col : Word; init_sym : Char); {!} PROCEDURE Print; VIRTUAL {метод вывода Sym } END; CONSTRUCTOR ObjSym.Init; BEGIN ObjPos.Init( init_line, init_col ); { задание позиции } Sym := init_sym { задание значения символа } END;

Рис. 13.7 {284}

PROCEDURE ObjSym.Print; BEGIN CRT.GotoXY( Col, Line ); { процедура из модуля CRT } Write( Sym ) { вывод символа в позиции } END; TYPE ObjString=OBJECT( ObjPos ) SubSt : String; { поле-значение подстроки } { ! } CONSTRUCTOR Init(init_line,init_col: Word; init_ss : String); { ! } PROCEDURE Print; VIRTUAL {метод вывода SubSt } END; CONSTRUCTOR ObjString.Init; {инициализация полей объекта } BEGIN ObjPos.Init( init_line, init_col ); {задание позиции } SubSt := init_ss { задание значения подстроки } END; PROCEDURE ObjString.Print; BEGIN CRT.GotoXY( Col, Line }; {процедура из библиотеки CRT } Write( SubSt ) {печать подстроки в позиции } END; {Вывод полиморфного объекта (строки или символа) } PROCEDURE PrintObj( VAR Obj : ObjPos ); BEGIN Obj.Print END; { =========== ТЕЛО ОСНОВНОЙ ПРОГРАММ ================ } VAR ObjSymVar : ObjSym; { экземпляр типа ObjSym } ObjStringVar : ObjString; { экземпляр типа ObjString } BEGIN { Инициализация и вывод: } ClrScr; { очистка экрана } ObjSymVar.Init( 10, 10, '*' ); ObjStringVar.Init( 20, 20, '...ПОДСТРОКА...' ); PrintObj( ObjStringVar ); { вывод строки } PrintObj( ObjSymVar ); { вывод символа } END.

Рис. 13.7 (окончание) {285}

Весьма важным является наличие слова VAR перед формальным параметром в процедуре PrintObj. В этом случае мы передаем сам объект. Если бы в процедуре PrintObj формальный параметр был описан как параметр-значение (без слова VAR), то процедура работала бы с копией объекта, приведенной к типу формального параметра. В примере на рис. 13.7 это выразилось бы в том, что несмотря на виртуальность методов, вызывался бы метод ObjPos.Print из типа формального параметра.



<== предыдущая лекция | следующая лекция ==>
Статические методы | Выбор вида метода


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 2.516 сек.