星辰日月00

欲多则心散,心散则志衰,志衰则思不达也!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Unit references and the uses clause(单元引用和uses 子句)
uses 子句列出了被程序、库或单元引用的单元(关于库,请参考库和包)。一个uses 子句可以出现
在:
 程序或库的工程文件
 单元的接口部分,和
 单元的实现部分
大多数工程文件包含一个uses 子句,大多数单元的接口部分也是如此,单元的实现部分也可以包含
自己的uses 子句。
System 单元自动被每个程序所引用,并且不能在uses 子句中明确列出来(System 单元实现文件
I/O、字符串处理、浮点运算、动态内存分配等例程)。其它一些标准单元,比如SysUtils,必须包含在
uses 子句中。大多数情况下,当由工程创建和维护源文件时,所有必需的单元将被包含在uses 子句中。
在单元声明以及uses 子句中(尤其是在Linux 下),单元名称必须和文件名大小写一致。在其它情
况(比如使用限定符的标志符),单元名是大小写无关的。要避免在单元引用中出现问题,要明确指出单
元文件:
uses MyUnit in "myunit.pas";
如果像上面这样在工程文件中明确引用一个单元,在其它源文件中就可以像下面那样简单地引用它,
而不必考虑大小写问题:
uses Myunit;
关于uses 子句的内容和使用位置,请参考多重和间接单元引用以及循环单元引用。

The syntax of a uses clause(uses 子句的语法)
一个uses 子句由关键字uses、后面跟一个或多个由逗号隔开的单元名,最后是一个分号构成。举例
如下:
uses Forms, Main;
uses Windows, Messages, SysUtils, Strings, Classes, Unit2, MyUnit;
uses SysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs;
在程序或库(工程)的uses 子句中,任何单元名后面可以跟关键字in 和一个(单元)源文件名:
源文件名用单引号括起来,可包括或不包括路径,路径可以是绝对路径,也可以是相对路径。举例如下:
uses Windows, Messages, SysUtils, Strings in 'C:\Classes\Strings.pas', Classes;
uses
 QForms,
 Main,
 Extra in '../extra/extra.pas';
当要指定单元源文件时,在单元的名称后面包含in…。因为IDE 期望单元名和它所在的源文件名相
同,所以通常没有理由这样做。只有当单元源文件的位置不明确时,你才需要使用in 关键字。比如,当
 引用的单元文件和工程文件在不同的目录,并且单元所在的目录没有包含在编译器搜索路径、
也不在库搜索路径中
 编译器的不同搜索路径中有同名的单元
 你在命令行编译一个控制台程序,并且单元名和它的文件名不同
编译器也根据in…来判断哪些单元是工程的一部分。在工程文件(.dpr)的uses 子句中,只有后面
包含in 和一个文件名的单元才被认为是工程的一部分,而其它单元只是被工程引用而不属于这个工程。
这种区别对编译程序没有影响,但它影响IDE 工具,比如Project Manager 和Project Browser。
在单元的uses 子句中,你不能用in 告诉编译器到哪里寻找单元文件。每个单元文件必须位于编译
器搜索路径、或库搜索路径中,或者和引用它的单元文件位于同一路径;而且,单元名必须和它们的单
元源文件同名。

Multiple and indirect unit references(多重和间接单元引用)
在uses 子句中,单元出现的顺序决定了它们的初始化顺序(请参考初始化部分),也影响编译器对
标志符的定位。如果两个单元声明了具有相同名称的变量、常量、类型、过程和函数,编译器使用uses
子句中列在后面的那个单元所声明的标志符。若要访问其它单元的标志符,你必须添加限定符:
UnitName.Identifier。
在uses 子句中,你只需列出被程序或单元直接引用的单元。也就是说,如果单元A 使用单元B 中
声明的常量、变量、类型、过程或函数,则A 必须明确引用单元B;若单元B 引用单元C 的标志符,则
单元A 是间接引用单元C。这种情况下,在单元A 的uses 子句中不必包含C,但编译器为了处理A,
它还是必须能找到B 和C。
下面的实例演示了间接引用:
program Prog;
uses Unit2;
const a = b;
...
unit Unit2;
interface
uses Unit1;
const b = c;
...
unit Unit1;
interface
const c = 1;
...
在这个例子中,Prog 直接引用单元Unit2,Unit2 又直接引用单元Unit1,因此,Prog 间接引用
Unit1。因为Unit1 没出现在Prog 的uses 子句中,在Unit1 单元声明的标志符对Prog 是不可见的。
要编译一个客户模块,编译器需要定位客户模块所引用的所有单元,不管是直接的还是间接的。但
是,除非这些单元的源文件发生了改变,否则,编译器只需要它们的 .dcu 文件(Windows)或 .dcu/.dpu
文件(Linux),而不是它们的源文件(.pas)。
当一个单元的接口部分被修改时,引用它的其它单元必须被重新编译;但若只修改了单元的实现部
分或其它部分,引用它的单元没必要重新编译。编译器自动跟踪依赖关系,只有在需要时才重新编译单
元。

Circular unit references(循环单元引用)
当单元间直接或间接地互相依赖(或引用)时,我们称这些单元为相互依赖。相互依赖是被允许的,
只要在接口部分的uses 子句中不出现循环引用路径。换句话说,从一个单元的接口部分开始,沿着它所
依赖的其它单元的接口部分的依赖路径,一定不能重新返回到这个单元。解决相互依赖问题的一种模式
就是,每个循环引用必须至少有一个uses 子句出现在实现部分。
在两个单元相互依赖这种最简单的情况下,你不能在它们的接口部分的uses 子句中互相列出对方。
所以,下面的例子将产生编译错误:
unit Unit1;
interface
uses Unit2;
...
unit Unit2;
interface
uses Unit1;
...
但是,若把其中的一个引用移到实现部分,这两个单元之间的相互引用将是合法的:
unit Unit1;
interface
uses Unit2;
...
unit Unit2;
interface
...
implementation
uses Unit1;
...
为了减少出现循环单元引用的机会,要尽可能在实现部分的uses 子句中引用单元。只有当来自另一
个单元的标志符必须在接口部分使用时,才需要在接口部分的uses 子句中引用它。

posted on 2012-01-31 13:14  星辰日月00  阅读(166)  评论(0编辑  收藏  举报