delphi基本语法

By | 10月24日
Advertisement

//delphi中exit,abort,break,continue 的区别

exit: 退出函数体
abort: 遇到异常,安静处理,就是不显示不提示
break: 退出当前循环体,包括for ,while, repeat等循环体
continue: 结束循环内的本次处理,继续从循环体的开始位置继续执行

Exit 是跳出当前代码块,也就是当前函数,跳出后是要继续向下执行的(如果有后续代码)。

Abort 是从 EAbort 过来的,可以激发 exception,其实质就是 Abort = RaiseException(),是一个不出现对话框的异常。所以 Abort 的行为和异常是一样的,其代码执行顺序也是follow异常的流程。
例如:
try
(1) //执行了
abort;
(2) //不执行
exception
(3) //执行了
end;

用 Abort 能够执行 exception 里边的代码,但是如果用 Exit,就直接离开,不管 exception。

例如:
procedure p1;
begin
p2;
p3;
end;
procedure p2;
begin
abort; //exit;
end;
procedure p3;
begin
//showmessage()..
end;

如果用 Abort,则执行不到 P3,如果用 Exit 就能够执行到 P3

******************************************************************************

在Delphi过程、函数中传递参数几个修饰符为Const、Var、Out。另一种不加修饰符的为默认按值传递参数。
一、默认方式以值方式传递参数
procedure TForm1.ProcNormal(Value: string);
begin
OrigNum:=Value+' Me';
lblReturn.Caption:=OrigNum;//OrigNum为'Hello Me'
lblOrig.Caption:=Value;//Value为'Hello'
end;

调用:
OrigNum:='Hello';
ProcNormal(OrigNum);

二、以Const方式传递参数,这个参数在调用过程中不能改变,并且这种方式会被编译器优化,一般建议尽可能地使用这种方式。
procedure TForm1.ProcConst(const Value: string);
begin
OrigNum:=Value+' Me';
lblReturn.Caption:=OrigNum;//为'Hello Me‘
lblOrig.Caption:=Value;//为'Hello Me'
end;

三、按引用方式传递参数
procedure TForm1.ProcRef(var value: string);
begin
OrigNum:=Value+' Me';
lblReturn.Caption:=OrigNum;//为'Hello Me‘
lblOrig.Caption:=Value;//为'Hello Me'
end;

四、按Out方式传递参数,这个方式传递参数时,参数可以不被初始化,即使有值也被忽视,它一般用于输出,它可以实现在一个过程中返回多个值,我们通常在分布式对象模型,如COM中使用它。
procedure TForm1.ProcOut(out Value: string);
begin
OrigNum:=Value+' Me';
lblReturn.Caption:=OrigNum;//为'Me'
lblOrig.Caption:=Value;//为'Me'
end;

五、无类型参数,这是一种较为特殊的方法,参数的类型不确定,只能用Const、Var、Out修饰,不能用于值方式传递参数,具体使用示例如下:
procedure TForm1.ProcUntype(const Value);
begin
OrigNum:=string(Value)+' Me';
lblReturn.Caption:=OrigNum;//为'Hello Me'
lblOrig.Caption:=string(Value);//为'Hello Me'
end;

六、默认参数,即如果此参数在调用时未提供时,将使用默认值。
procedure TForm1.ProcDefault(const Value, constDefaultValue:string=' 123');
begin
OrigNum:=Value+' Me'+DefaultValue;
lblReturn.Caption:=OrigNum;//为'Hello Me 123'
lblOrig.Caption:=Value;// 为'Hello Me 123'
end;

七、开放数组参数,即参数数组的元素个数不确定。
procedure TForm1.ProcArray(const Value: array of string);
var
i:Integer;
begin
for i:=Low(Value) to High(Value) do
OrigNum:=OrigNum+Value[i];//调用后为'Hello abc dbd'
lblReturn.Caption:=OrigNum;
end;

调用:

OrigNum:='Hello';
ProcArray([' abc ',' dbd']);

八、无类型开放数组参数,即类型及元素个数皆不确定。在WIN32平台中,这个参数的类型实际为array ofTVarRec,其使用示例如下:
procedure TForm1.ProcArrayConst(const Value: array of const);
var
i:Integer;
begin
for i:=Low(Value) to High(Value) do
with Value[i] do
case VType of
vtAnsiString: OrigNum:= OrigNum+String(VAnsiString);
vtInteger: OrigNum:=OrigNum+IntToStr(VInteger);
vtBoolean: OrigNum := OrigNum + BoolToStr(VBoolean);
vtChar: OrigNum := OrigNum + VChar;
vtExtended: OrigNum := OrigNum + FloatToStr(VExtended^);
vtString: OrigNum := OrigNum + VString^;
vtPChar: OrigNum := OrigNum + VPChar;
vtObject: OrigNum := OrigNum + VObject.ClassName;
vtClass: OrigNum := OrigNum + VClass.ClassName;
vtCurrency: OrigNum := OrigNum + CurrToStr(VCurrency^);
vtVariant: OrigNum := OrigNum + string(VVariant^);
vtInt64: OrigNum := OrigNum + IntToStr(VInt64^);
end;
lblReturn.Caption:=OrigNum;//调用后为'Hello abc 3'
end;

调用:

OrigNum:='Hello';
ProcArrayConst([' abc ',3]);

以上就是常见几种传递参数的方式。

//另一篇文章关于delphi参数传递的//

delphi参数传递

参数传递

声明/实现一个过程使用的参数称为形式参数(简称形参),调用过程时传入的参数称为实际参数(简称实参)。

{ Info是形参}

procedure ShowInfo(Info: String);

begin

ShowMessage(Info);

end;

var

S: String;

begin

S := 'lxpbuaa';

{S是实参}

ShowInfo(S);

end;

参数传递分两种:按值(by val)和引用(by ref)。这两种方式的本质区别是:

按值传递时,形参和实参是两个变量,它们开始时的值是相同的,即实参的数据被拷贝一份传递给了形参。所以此时,形参的改变不会影响到实参。

引用传递时,形参和实参是同一个变量,可以将它们之一看做是另一个的别名。 所以此时,形参改变时,实参跟着改变。

默认情况下,参数是按值传递的,传递的是数据拷贝;如果加了var前缀,则成了引用传递。

我们看如下例子:

procedure TForm1.ByVal(I: Integer); {按值传递I}

begin

ShowMessage(IntToStr(Integer(@I)));

{取得形参所在地址。你会发现它和实参地址是不同的,因为此时实参和形参是不同的两个变量}

I := I + 1;

end;

procedure TForm1.ByRef(var I: Integer); {引用传递I}

begin

ShowMessage(IntToStr(Integer(@I)));

{取得形参所在地址。你会发现它和实参地址是相同的,因为此时实参和形参是同一个变量}

I := I + 1;

end;

procedure TForm1.Button1Click(Sender: TObject);

var

I: Integer;

begin

I := 1;

ShowMessage(IntToStr(Integer(@I))); {取得实参所在地址}

ByVal(I); { I =1}

Showmessage(i); {i:=1;实参没有变}

ByRef(I); { I =2}

showmessage(i); {i:=2,实参改变了}

end;

按值传递的参数可以指定默认值,比如上面的ByVal可以是这样:

procedure ByVal(I: Integer = 0);

调用它时可以省掉有默认值的参数:ByVal。带默认值的参数必须位于参数列表的最后,如:

procedure ByVal(I: Integer = 0; B: Boolean);

是不行的,应该改为:

procedure ByVal(B: Boolean; I: Integer = 0);

因为默认值必须是一个常数表达式,所以dynamic-array、procedural、class、class-reference和 interface等参数只能指定nil默认值;而record、variant、file和static-array等类型的参数则根本不能指定默认 值。

如果按值传递一个指针类型的参数,情况会变得复杂而又很有意思。此时,实际传递的是什么呢?是实际数据的拷贝吗?不,是指针的拷贝,也就是说形参和实参是 两个指针,不过这两个指针指向了相同地址。所以这时候,形参和实参可以共享它们指向地址中的数据,但如果改变了形参的指针指向,实参的指针指向不能跟着改 变。那么总结一下,就是:按值传递指针参数时,实参和形参可以共享指针指向地址中的数据,但是不能共享指针本身的指向。而引用传递时,因为实参和形参是同 一个变量,因此实现完全共享。看下面的例子:

procedure TForm1.ByVal(Obj: TObject);

begin

Obj := Button1;

{改变形参指针指向,实参的指针指向不会跟着改变,因为它们是两个变量。如果仅仅是改变Obj的属性而不改变指向,则实参的属性会跟着改变}

end;

procedure TForm1.ByRef(var Obj: TObject);

begin

Obj := Button1;

{改变形参指针指向,实参的指针指向跟着改变,因为它们是同一个变量}

end;

procedure TForm1.Button1Click(Sender: TObject);

var

Obj: TObject;

begin

Obj := Self;

{Self即Form1,所以此时实参Obj的类名(ClassName)是"TForm1"}

ByVal(Obj); {按值传递指针变量Obj}

ShowMessage(Obj.ClassName); {显示类名"TForm1"}

ByRef(Obj); {引用传递指针变量Obj}

ShowMessage(Obj.ClassName); {显示类名"TButton1"}

end;

上面讲了这么多,最根本的还是一句话:按值传递时,形参和实参是两个变量;引用传递时,形参和实参是同一个变量。抓住这句话,就等于抓住了一切。(ps:关键总结):

相信你还看到过如下格式的参数声明:

function CompareStr(const S1, S2: string): Integer;

function TryStrToInt(const S: string; out Value: Integer): Boolean;

其中使用了const和out关键字。如果你没有看到过这样的声明,也不要紧,它们是真实存在的。

const声明的参数是按值传递的,而且形参不能被改变。

out声明的参数是引用传递的,主要用于定义输出参数,也就是说不需要输入值(即实参不需要初始化),实参传递给形参的值被忽略。

如果用const修饰指针参数,那么只能通过形参修改指针地址里的数据而不能修改指针本身的指向。例如对于一个const对象参数,可以修改其属性,但是不能将它指向其他对象。例如:

procedure ShowInfo(const Form: TForm);

begin

{以下一句不能通过,编译器提示:[Error] Unit1.pas(28): Left side cannot be assigned to}

{Form := Form1;}

{但是通过其属性或者方法修改隶属于Form的数据}

Form.Caption := 'lxpbuaa';

ShowMessage(Form.Caption);

end;

在本小节的最后,还不得不提及一种很特殊的参数类型:无类型参数(Untyped parameters)。

声明时没有指定数据类型的参数称为无类型参数。因此,从语法上讲,无类型参数可以接收任何类型的数据。

无类型参数必须加const、out或var前缀;无类型参数不能指定默认值。

如以下一些Delphi定义的过程都使用了无类型参数:

procedure SetLength(var S; NewLength: Integer); {参数S}

procedure Move(const Source;var Dest;Count:Integer); {参数Source、Dest}

procedure TStream.WriteBuffer(const Buffer; Count: Longint);{参数Buffer}

所谓无类型参数可以接收任何类型的值,只是从语法角度而言的。或者说,理论上我们可以实现一个可以使用任何类型变量作为参数的过程,但是实际上没有必要,也不可能做到。

打个比方说,我们想造一辆可以装载任何物体的汽车。因为是“任何物体”,所以物体可能是任何形状,于是这辆车必须没有车篷,除了在几个车轮上铺一个足够大 (足够大就已经是个大问题了)的平板外,不能再有任何东西。这时候,这个平板就可以看做是无类型的,因为它上面可以坐人、摆一张桌子,也可以赶一些动物上 去站着或者躺着。尽管它可以承载很多种类的东西,但是也是有限制的,比如不能放一座山、也无法容纳1万头猪。所以无类型参数的类型往往是有一定限制的。比 如SetLength的参数S只能是字符串、动态数组等。

这种限制一般是在过程的实现中完成的,在运行时检查参数值的实际类型。对于与开发环境关系紧密的参数,限制也可以构筑在编译器里。

使用无类型参数的原因是无法在声明时使用一个统一的类型来描述运行时可能的类型,如SetLength的参数S可以是字符串和动态数组,而并没有一个统一 的类型来代表字符串和动态数组类型,所以干脆声明为无类型。而将类型限制放到别的地方实现(如编译器)。例如SetLength的限制规则是写在编译器中 的,它只能作用于长字符串或者动态数组。你企图完成下面的功能时:

var

I: Integer;

begin

SetLength(I, 10);

end;

编译器编译时将给出错误信息:[Error] Unit1.pas(35): Incompatible types。导致编译中断。

小结

本小节的内容比较重要,重点是理解参数按值传递和引用传递的本质:按值传递时,形参和实参是两个变量;引用传递时,形参和实参是同一个变量。

声明指令

声明一个过程,可以使用register、pascal、cdecl、stdcall和safecall指令来指定参数传递顺序和参数内存管理方式,从而影响过程的运作。如:

function MyFunction(X, Y: Integer): Integer; cdecl;

这五个指令具有不同含义,如表3-1所示。

表3-1 五个指令的不同含义

指令 参数存放位置 参数传递顺序 参数内存管理 适用地点

register CPU寄存器 从左到右 被调用者 默认.published属性存取 方法 必须使用

pascal 栈 从左到右 被调用者 向后兼容,不再使用

cdecl 栈 从右到左 调用者 调用C/C++共享库

stdcall 栈 从右到左 被调用者 API调用,如回调函数

safecall 栈 从右到左 被调用者 API调用,如回调函数。双

在一些源代码(包括Delphi自带的VCL源代码)中,你还可能看到near、far、export以及inline、assemble等指令,它们是 为了和16位Windows系统或者早期Pascal/Delphi兼容,在目前的Delphi版本中,已经不具有任何意义,所以在新的开发中不要再使 用。

Similar Posts:

  • Delphi 正则表达式语法

    在 Delphi 中使用正则表达式, 目前 PerlRegEx 应该是首选, 准备彻底而细致地研究它. 官方网站: http://www.regular-expressions.info/delphi.html 直接下载: http://www.regular-expressions.info/download/TPerlRegEx.zip 安装方法: 1.先把解压的 TPerlRegEx 文件夹放一个合适的地方, 我放在了 Delphi 的 Imports 目录中. 2.目前最新 For Wi

  • Delphi基础语法的学习笔记和注意事项总结

    以下是我在自学Delphi的时候,对一些注意点的简单总结,并没有什么系统性可言,只是一个学习时顺手记下的笔记,主要为了当时加深对知识的印象,并没有希望能在以后的复习和使用Delphi中有什么多大的参考作用. 缺少Delphi的各种数据类型的介绍--知识点. 1. Delphi编译器自动对全局变量符初值.当程序开始时,所有的整型变量赋值为0,浮点数赋值为0.0,指针为null,字符串为空等等,因此,在源代码中不必对全局变量赋0初值 2. Object Pascal允许在const和var声明的时候

  • delphi if语法,弹出提示框,不等于写法,判断是否为空

    初学Delphi procedure TFrmLltj.cbb_xxlkChange(Sender: TObject); begin if Trim(cbb_xxlk.Text)<>'' then begin Showmessage('没空'); end else Showmessage('空了'); end; end. if语法: if .. then begin end else end; 弹出提示框:Showmessage(''); 不等于写法:<> 黑色头发:http://

  • Delphi 正则表达式语法(5): 边界

    // \b 单词边界 var reg: TPerlRegEx; begin reg := TPerlRegEx.Create(nil); reg.Subject := 'Delphi Delphi2007 MyDelphi'; reg.RegEx := '\bDelphi\b'; //前后边界 reg.Replacement := '◆'; reg.ReplaceAll; ShowMessage(reg.Subject); //返回: ◆ Delphi2007 MyDelphi FreeAndN

  • 在Richedit上进行Delphi代码语法加亮显示

    procedure CodeColors(Form : TForm;Style : String; RichE : TRichedit;InVisible : Boolean); const // symbols... CodeC1: array[0..20] of String = ('#','$','(',')','*',',', '.','/',':',';','[',']','{','}','<','>', '-','=','+','''','@'); // reserved word

  • Pascal、VB、C#、Java四种语法对照表

    因为工作原因,自学会了vb后陆续接触了其它语言,在工作中经常需要与各家使用不同语言公司的开发人员做程序对接,初期特别需要一个各种语法的对照比,翻看了网络上已有高人做了整理,自己在他基础上也整理了一下,摘抄如下(最后附上原作,网上也可以找到): 类别 Vb6 & Vb.Net Delphi C# 语法 不区分大小写 不区分大小写 区分大小写 数据类型 数据 关键字 占用字节 类型符 整型 integer 长整型 long 单精度型 single 双精度型 double 货币型 currency 字

  • 重新温习Delphi,真是郁闷死

    换了单位,接了个新项目,居然还要用delphi和c.习惯了一年多的c#,突然要用许久不摸的delphi,真是郁闷.忘记了还无所谓,只是看到delphi那些语法规定,忽然好怀念c#的简洁与美丽啊.今天看到博客园上的c#代码,几乎都有一种想哭的冲动啊! 郁闷~~~(总之,.Net我还是不会丢弃的.)

  • DELPHI程序的调试与异常处理

    任何一种流行的高级语言编译器都提供了较易使用的调试与异常处理的方法.当然不同的编译器因为其编译的原理不同导致其调试的具体方法和异常处理的具体技巧也有所不同.比如说VB,因为它是解释型的语言,所以象单步跟踪这样的方式可以一边编译一边查看执行结果,因为它的每一条语句本来就是一边运行一边解释再返回结果的:而象VC,相对起来则要等待“很长”的编译过程,这时候写几行代码就调试结果的习惯就会变得非常痛苦. 正 因为这些原因,所以我觉得调试技巧和异常处理的具体写法跟一个程序员的编码风格有关,也与开发工具的实现

  • Pascal语法的技巧

    每天都有新的发现. 3月5日:-----------------------幂的运算符fp中 a**b 相当于delphi 中pow(a,b)-----------------------2进制:%x8进制:&x16进制:$xchar型:#xe.g.#%1010111&12356 -----------------------array of TYPE e.g.function sum(A: array of Integer):integer;var i:integer;begin res

  • Delphi正则表达式处理集合

    Delphi 正则表达式之TPerlRegEx 类的属性与方法(7): Split 函数 Delphi 正则表达式之TPerlRegEx 类的属性与方法(6): EscapeRegExChars 函数 Delphi 正则表达式之TPerlRegEx 类的属性与方法(5): Compile.Study Delphi 正则表达式之TPerlRegEx 类的属性与方法(4): Replace Delphi 正则表达式之TPerlRegEx 类的属性与方法(3): Start.Stop Delphi 正

Tags: