10.6 Циклические ссылки на модули
Рассмотрим следующие программу и два модуля:
Program MainProg ; { Выводит текст, используяWriteXY}
Uses Crt, Display ;
Begin
ClrScr ;
WriteXY ( 1, 1, ‘Левый верхний угол экрана’ ) ;
WriteXY ( 100, 100, ‘За пределами экрана’ ) ;
WriteXY ( 81 - Length ( ‘Снова в экран…’ ), 15, ‘Снова в экран…’ )
End.
Unit Display ; { Содержит процедуру выводаWriteXY }
Interface
Procedure WriteXY ( X, Y : Integer ; Message : String ) ;
Implementation
Uses
Crt, Error ;
Procedure WriteXY ;
Begin
If ( X in [1..80] ) and ( Y in [1..25] )
then
Begin
gotoXY ( X, Y ) ;
Write ( Message )
End
else
ShowError ( ‘Неверные координаты в WriteXY’ )
End
End.
Unit Error ; { Содержит процедуру обработки ошибки }
Interface
Procedure ShowError ( ErrMsg : String ) ;
Implementation
Uses
Display ;
Procedure ShowError ;
Begin
WriteXY ( 1, 25, ‘Ошибка: ’ + ErrMsg )
End
End.
Видим, что основная программа MainProgиспользует модульDisplay, который содержит в своей интерфейсной секции одну процедуруWriteXY. Последняя перемещает курсор в заданную точку и выводит там заданное сообщение. В противном случае она вызывает процедуру обработки ошибкиShowError, которая содержится в модулеError. Когда процедура обработки ошибки будет выводить сообщение на экран, начинаются циклические ссылки — она использует процедуруWriteXYизDisplay.
Видим также, что предложения Usesвсекции реализацииобоих модулей ссылаются друг на друга (что и обеспечивает возможность циклических ссылок). Это можно сделать потому, что компилятор может для обоих модулей выполнить полную компиляциюинтерфейсных секций.
Другими словами, компилятор воспринимает ссылку на частично скомпилированный модуль Aвсекции реализации модуляB, еслиинтерфейсные секции модулейAиBне зависят друг от друга.
10.7 Совместное использование описаний
Введем в процедуры из предыдущего примера дополнительный параметр, задающий прямоугольное окно на экране:
Procedure WriteXY ( SomeWindow : WindRec ; X, Y : Integer ; Message : String ) ;
Procedure ShowError ( SomeWindow : WindRec ; ErrMsg : String ) ;
Две процедуры находятся в разных модулях. Даже если описать WindRecв интерфейсной секции одного модуля, то это описание не будет доступно в другом модуле. Выход состоит в том, чтобы описать третий модуль, в котором содержится только описание записиWindRec:
Unit WindData ;
Interface
Type
WindRec = Record
X1, Y1, X2, Y2 : Integer ;
. . .
End ;
Implementation
End.
Теперь необходимо в интерфейсной секции модулей DisplayиErrorв предложенииUsesдобавить имя модуляWindData. Это допустимо, т.к. модульWindDataне зависит от своего предложенияUses, а модулиDisplayиErrorссылаются друг на друга только в секциях реализации.