Важно помнить, что таблица виртуальных методов — одна для каждого типа, а не у каждой переменной типа «объект». Переменная лишь держит связь с таблицей своего типа, и эта связь устанавливается конструктором. В объекте может быть определено несколько конструкторов. Сами конструкторы могут быть только статическими, хотя внутри конструктора могут вызываться и виртуальные методы.
При передаче в процедуру или функцию полиморфного объекта, имеющего виртуальные методы, адреса этих методов передаются
- 284 -
через соответствующую объекту таблицу 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
- 285 -
| 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 { задание значения подстроки }