1. Если прародительский тип объекта описывает метод как виртуальный, то все его производные типы, которые реализуют метод с тем же именем, должны описать этот метод тоже как виртуальный. Другими словами, нельзя заменять виртуальный метод статическим. Если же это произойдет, компилятор сообщит об ошибке номер 149 VIRTUAL expected («Ожидается служебное слою VIRTUAL»).
2. Если переопределяется реализация виртуального метода, то заголовок заново определяемого виртуального метода в производном типе не может быть изменен. Иначе говоря, должны остаться неизменными порядок расположения, количество и типы формальных параметров в одноименных виртуальных методах. Если этот метод реализуется функцией, то не должен изменяться и тип результата. При изменении заголовка метода компилятор выдаст сообщение об ошибке номер 131 Header does not match previous definition («Заголовок не соответствует предыдущему определению»).
- 283 -
3. В описании объекта должен обязательно описываться специальный метод, инициализирующий объект (обычно ему дают название Init). В этом методе служебное слово PROCEDURE в объявлении и реализации должно быть заменено на слово CONSTRUCTOR. Это служебное слово обозначает особый вид процедуры — конструктор, который выполняет установочную работу для механизма виртуальных методов. Все типы объектов, которые имеют хотя бы один виртуальный метод, должны иметь конструктор. Конструктор всегда вызывается до первого вызова виртуального метода. Вызов виртуального метода без предварительного вызова конструктора может привести систему к тупиковому состоянию, а компилятор не проверяет порядок вызовов методов. Помните об этом!
13.5.2.2. Конструкторы и таблица виртуальных методов. Каждый экземпляр (переменная) типа «объект», содержащий виртуальные методы, должен инициализироваться отдельным вызовом конструктора. Если переменная А инициализирована вызовом конструктора, а переменная В того же типа не инициализирована, то присваивание В:=А не инициализирует переменную В и при вызове ее виртуальных методов программа может «зависнуть».
Чтобы понять, что делает конструктор, разберемся в механизме реализации виртуальных методов. Каждый объектный тип (именно тип, а не экземпляр) имеет «таблицу виртуальных методов» (VMT), которая содержит размер типа объекта и адреса кодов процедур или функций, реализующих каждый из его виртуальных методов. При вызове виртуального метода каким-либо экземпляром местонахождение кода реализации этого метода определяется по таблице VMT для типа этого экземпляра. Конструктор же устанавливает связь между экземпляром, который вызывает конструктор, и таблицей виртуальных методов данного объектного типа. Если же конструктор не будет вызван до обращения к виртуальному методу, то перед компьютером станет вопрос, где же искать этот метод. Это и приведет к тупиковой ситуации.