====== 分隔線==================
在Delphi中,也有与C相似的预编译指令,虽然该类指令只在当前的单个文件有效(也有可能是笔者未全面了解该类指令的真正用法),但是这一类指令对于进行多版本的制作工作(如从标准版中出学习版),确实有着相当不错的用途。


一.指令介绍:

1. DEFINE指令:

格式:{$DEFINE 名称}

说明 :用于定义一个在当前单元有效的符号(Symbol)。定义了

之后可以使用IF DEF和IFNDEF指令来判断该符号是否存在。


2. UNDEF指令:

格式:{$UNDEF 名称}

说明:用于取消一个在当前单元已经定义的符号(Symbol)。该指令和DEFINE

配合使用。


3. IFDEF指令:

格式:{$IFDEF 名称}

说明:如果该指令后的名称已经定义,则编译该指令后直到{$ELSE}或{$ENDIF}之间的代码段。


4. IFNDEF指令:

格式:{$IFNDEF 名称}

说明:如果该指令后的名称没有定义,则编译该指令后直到{$ELSE}或{$ENDIF}之间的代码段。


5. IFOPT指令:

格式:{$IFOPT 开关}

说明:如果该指令后的开关已经设立,则编译该指令后直到{$ELSE}或{$ENDIF}之间的代码段。

举例:{$IFOPT R+}

Writeln('编译时打开范围检查开关');

{$ENDIF}


6. ELSE指令:

格式:{$ELSE}

说明:通过判断前缀Ifxxx的条件式来确定该指令到{$ENDIF}之间的代码段是否应该被编译或者忽略掉。


7. ENDIF指令:

格式:{$ENDIF}

说明:和Ifxxx配合,指明条件预编译段源代码段的结束位置。


二.范例:

编写例子,通过预先定义不同的编译符号,进行不用代码段的编译工作。

1. 新建一个Delphi项目,在Unit1单元的窗体上添加一个Button按钮。

2. 编写程序如下:

unit Unit1;


interface


uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls;

type

TForm1 = class(TForm)

Button1: TButton;

procedure FormCreate(Sender: TObject);

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

a : String;

end;


var

Form1: TForm1;


implementation


{$R *.DFM}


{$DEFINE AAA} // 定义行。


procedure TForm1.FormCreate(Sender: TObject);

begin

a := 'Other';

{$IFDEF AAA}

a := 'AAA';

{$ENDIF}

{$IFDEF BBB}

a := 'BBB';

{$ENDIF}

end;


procedure TForm1.Button1Click(Sender: TObject);

begin

Caption := a;

end;


end.

{注:粗体字部分为输入的代码}

3. 编译后运行,按下Button,则看到窗体标题栏显示“AAA”。程序编译了a := ’AAA’的语句。

4. 改变定义行的程序段:

当改为

{$DEFINE BBB}

时,再次编译运行,则看到窗体标题栏显示“BBB”。程序编译了a := ’BBB’的语句。

当取消定义行或改为

{$DEFINE NOTHING}

或其他名称时,再次编译运行,则看到窗体标题栏显示“Other”。程序只编译了a := ’Other’的语句。


三.如何快速的制作和更改版本:

(1)使用预编译指令,在制作同一个程序的多个版本时,只需找出各版本中有区别的单元,依次定义统一的版本符号(Symbol),然后在程序段中加入条件预编译指令,就可以在实际编译中取舍编译不同的程序部分,这样对于程序的规范性(定义统一的版本符号)和保密性(不同的版本编译不同的程序部分)有很好的作用。

然而,由于该类预编译指令只能作用于当前单元,所以不便之处在于不能在一个公共单元定义一次版本符号,而必须在各单元中定义统一版本符号才行,故此,在更换版本时,需要确定所有的版本符号都已改变,这样才能保证各版本的正确性,对此,可以使用Delphi IDE的“Find in Files…”(多个文件中查找字符串)的功能,找出所有定义版本符号的文件和位置,然后依次更改,保证所有位置已经改正。

(2)在PROJECT|OPTIONS中Directories/Conditions 內Conditional Define中直接輸人入XXX即可,若不只一個則可用';'分開, 這樣會使XXX在整個project中均有定義

---------------------------------------------------------------

DELPHI的编译指令

{$IFDEF WIN32} -- 这可不是批注喔! 
    对于Delphi来说﹐左右大括号之间的内容是批注﹐然而「{$」(左括号后紧接着货币符号)对于Compiler(编译器)而言并不是批注﹐而是写给Compiler看的特别指示。 

应用时机与场合 

    Delphi中有许许多多的Compiler Directives(编译器指令)﹐这些编译指令对于我们的程序发展有何影响呢? 它们又能帮我们什么忙呢? 

    Compiler Directive 对程序开发的影响与助益, 可以从以下几个方向来讨论: 

协助除错 
版本分类 
程序的重用与管理 
设定统一的执行环境 
协助除错 

    稳健熟练的程序设计师经常会在开发应用系统的过程中﹐特别加入一些除错程序或者回馈验算的程序﹐这些除错程序对于软件品质的提升有极其正面的功能。然而开发完成的正式版本中如果不需要这些额外的程序的话﹐要想在一堆程序中找出哪些是除错用的程序并加以删除或设定为批注﹐不仅累人﹐而且容易出错﹐况且日后维护时这些除错程序还用得着。

    此时如果能够应用像是$IFDEF的Compiler Directives ﹐就可以轻易的指示Delphi要/不要将某一段程序编进执行文件中。 
同时﹐Compiler本身也提供了一些错误检查的开关﹐可以预先对程序中可能的问题提醒程序设计师注意﹐同样有助于撰写正确的程序。 

版本分类 

    除了上述的除错版本/正式版本的分类之外﹐对于像是「试用版」「普及版」「专业版」的版本分类﹐也可以经由Compiler Directive的使用﹐为最后的产品设定不同的使用权限。其它诸如「中文版」「日文版」「国际标准版」等全球版本管理方面﹐同样也可以视需要指示Delphi特别连结哪些资源档或者是采用哪些适当的程序。以上的两则例子中﹐各版本间只需共享同一份程序代码即可。 

    Delphi 1.0 与 Delphi 2.0有许多不同之处﹐组件资源文件(.DCR)即是其中一例﹐两者的档案格式并不兼容﹐在您读过本文之后﹐相信可以写出这样的程序﹐指示Delphi在不同的版本采用适当的资源文件以利于组件的安装。 

{$IFDEF WIN32} 
{$R XXX32.DCR} 
{$ELSE} 
{$R XXXX16.DCR} 
{$EDNIF} 

程序的重用与管理 

    经过前文的讨论后﹐相信你已经不难看出Compiler Directives在程序管理上的应用价值。对于原始程序的重用与管理﹐也是Compiler Directives 使得上力的地方. 举例来说: 

    Pascal-Style字符串是Delphi 1.0与 Delphi 2.0之间的明显差异﹐除了原先的短字符串之外﹐Delphi 2.0之后还多了更为方便使用的长字符串﹐同时﹐系统也额外提供了像是 Trim() 这样的字符串处理函式。假如您有一个字符串处理单元必须要同时应用于Delphi 1.0 与 2.0的项目时﹐编译指示器可以帮你的忙。 

    此外﹐透过像是{$I xxxx} 这样的 Compiler Directives﹐我们也可以适当的含入某些程序, 同样有助于切割组合我们的程序或编译设定。 

设定一致的执行环境 

    项目小组的成员间﹐必须有共同的环境设定﹐我很难预料一个小组成员间彼此有不同的{$B}{$H}{$X}设定﹐最后子系统在并入主程序时会发生什么事。 

此外, 当您写好一个组件或单元需要交予第三者使用时, 使用编译指示器也可以保证组件使用者与您有相同的编译环境。 

使用Compiler Directives 指令语法 

創作者介紹
創作者 翔雲 的頭像
翔雲

~雲居地~

翔雲 發表在 痞客邦 留言(0) 人氣()