Delphi语法基础
即Object Pascal的主要语法。
一,语句
程序、过程和函数都是由语句组成的,每个语句创建一个可执行的代码。要注意程序的可读性,在程序中选择合适的缩排、大小写风格,并在需要时将程序代码分行
1,语句(简单语句)格式:语句 + ;
2,语句块(复合语句,构造语句)格式:
Begin //Begin后面没有分号
语句1;
语句2; //End前面的分号可有可无
End; //End后面必须有分号或者句号(程序的最后一个End后面),以标记语句块或者程序的结束。
3,注释语句: {这是一个用于说明注释语句的例子
注释语句包含在”花括号 “和”花括号”中,称为块注释
或者包含在”圆括号* “和” *圆括号”中,是常用于屏蔽代码的块注释
或者两个反斜杠和换行符之中,称为行注释
//可以在块注释里面嵌套行注释
不同类的块注释符可以互相嵌套,但不提倡这么做。
}
{ ( *这是合法但不提倡的* ) }
( * {这是合法但不提倡的} * )
//块注释1,多个紧跟的行注释会形成一个块注释
//块注释2,许多文档注释分析工具(如:Doc-O-Matic)
//块注释3,会将注释块内的所有的句子自动连接在一起,形成一文字段落
//行注释4,被空行隔开的是独立的行注释
//## 这样的注释行会被工具忽略不提取
//有如下字符的注释也不会被提取。”Ignore Text”, “$Log”, “$Filename”, “$Revision”, “$Date”, “$Author”, “$History”, “$Id”
procedure TForm1.FormCreate(Sender: TObject);
var
MyButton : TButton;
begin //语句块包含在begin…end中
MyButton := TButton.Create(self); //语句以;结束
MyButton.Parent := self; //忽略空白字符(空格/回车/TAB)
//告诉创建方法在Form1中显示MyButton
(*MyButton.Caption := '测试一';*) //一般 (*…*)用于临时注释掉暂不使用的代码
MyButton.OnClick := MyButtonClick; //临时的注释可在注释符号后加上”???”以待修订
MyButton.Show;
end;
* 一些注释“{ }”标记后跟有“$”符号,编译开关{$j+};这些是编译指示,不可修改。编译指示一般包括对另一文的参考或用来改变代码的路径
* 还可以使用IDE帮助注解功能:可以在在线帮助中找到一个属性,Object Inspector中选定该属性值段,并按下F1键,则类型将在属性说明的结尾处列出,例如Color属性列出下边的语句:Property Color : TColor;
二,数据类型
Object Pascal的最大特点是,它的数据类型特别严谨,这表示传递给过程或函数的实参必须和定义过程或函数时的形参的类型相同。
6大基类型
范围 |
内存 |
|||
整型 |
Integer |
-32768到32767 |
2字节 |
没有小数部分的数字 |
Shortint |
-128到127 |
1字节 |
||
Longint |
-2147443648到2147483647 |
4字节 |
||
Byte |
0到255 |
1字节 |
||
Word |
0到65535 |
2字节 |
||
实型 |
Single |
4字节 |
可含7到8位有效小数 |
|
Double |
8字节 |
15到16位有效小数 |
||
Extended |
10字节 |
19到20位有效小数 |
||
Comp |
8字节 |
19到20位有效小数 |
||
Real |
专用于向前兼容,否则用Double或Extended |
6字节 |
11到12小数, |
|
布尔型 |
Boolean |
只包含true或False两个值 |
1字节 |
|
字符型 |
Char |
D2007为止是AnsiChar |
1字节 |
表示: 'a'或#97 ''''或#39 ' '空格 |
AnsiChar |
1字节的ANSI字符 |
|||
WideChar |
2字节的Unicode字符 |
|||
字符串型 |
String |
AnsiString 这是Pascal缺省的字符串类型 |
'Line 1'#13#10'Line 2' |
'You''ll see' { You'll see } |
AnsiString |
由AnsiChar 字符组成,其长度没有限制,同时与 n u l l结束的字符串相兼容 |
|||
ShortString |
为兼容D1而保留,最长255字符 |
|||
WideString |
由WideChar 字符组成,其长度没有限制,同时与 null结束的字符串相兼容 |
|||
PChar |
指向null结束的Char字符串的指针,类似于C的char * 或lpstr类型 |
|||
PAnsiChar |
指向null结束的AnsiChar字符串的指针 |
|||
PWideChar |
指向null结束的WideChar字符串的指针 |
|||
指针型 |
Pointer |
可以指向任何特定类型 |
||
1,字符在长度上并不表示一个字节,应该使用Sizeof( )函数对字符长度进行编码,Sizeof()标准函数返回类型或实例的字节长度。
2,字符串 参见Delphi 中的字符串——《Delphi6 开发人员指南》读书笔记
var
S:string; //编译器默认S的类型是AnsiString。可用编译开关$H来将未限长度的string类型定义为ShortString
var
{$H-} //当$H编译开关的值为负时,string变量是ShortString类型;
S1:string; //S1是ShortString类型
{$H+} //当$H编译开关的值为正时(缺省情况),字符串变量是AnsiString类型
S2:string; //S2是AnsiString类型
var
S: string[63]; //63个字符的ShortString字符串。如果在定义时特地指定了长度(最大在2 5 5个字符内),那么总是ShortString,$H规则无效
* AnsiString类型的内存分配原则:自动回收功能。
AnsiString字符串类型有引用计数的功能,这表示几个字符串都能指向相同的物理地址。因此,复制字符串因为仅仅是复制了指针而不是复制实际的字符串而变得非常快。
*,字符串运算符:能用+运算符或Concat( )函数来连接两个字符串,推荐使用+运算符,
*, “编译器魔术”字符串函数和过程:Concat ( )是众多“编译器魔术”过程和函数中的一个,其他还有ReadLn( )、WriteLn( )、它们没有Object Pascal的定义。这些函数接收不确定个数的参数或可选的参数,它们不能根据Object Pascal语言来定义,正因为这样,编译器为每一个这样的函数提供了特殊的条件,并产生一个对堆栈函数的调用,这些堆栈函数定义在S y s t e m单元中,它们为了越过P a s c a l的语言规则,通常是用汇编语言实现的。
3,变体类型:由于Va r i a n t类型提供了更灵活的机制,你可能想用Va r i a n t类型来代替传统的数据类型。然
而,这将增加程序代码长度,并使得程序运行起来很慢。另外它也使得程序代码很难维护。在
有些情况下Va r i a n t特别有用。事实上,V C L中有好几个地方都用到了v a r i a n t,尤其是在A c t i v e X
和数据库领域。因为这些地方需要复杂的数据类型。一般来说,应当使用传统的数据类型,除
非对灵活性的要求超过了对程序性能的要求。不确定的数据类型会产生不确定的缺陷。
4,Currency:在Delphi 2.0中引进了一种新的数据类型C u r r e n c y。它的主要目的是用来进行财经计算,它不同于
能在数字间移动小数点的浮点数,它的小数点是固定的,在小数前有1 5位数字,在小数点后有4位数字。
当移值Delphi 1.0的程序并涉及到货币时,最好用C u r r e n c y来代替S i n g l e、r e a l、D o u b l e和E x t e n d e d。
三,变量
1,标识符:
标识符包括变量(var)、常量(const)、类型(type)、过程(procedure)、方法(Method)及其他,Object Pascal 在应用标识符时,必须首先说明它们。Object Pascal是强类型语言,它的编译器可以检查确保赋给变量或属性的值是正确的类型,以便于您改正错误。因为Object Pascal是编译语言,所以Delphi的执行速度要比使用解释语言快得多。在使用标识符前说明它们,可以减少程序错误并增加代码的效率。
命名规则:字母或_+ 字母或_或数字 (最长255多则截断,不分大小写,勿用系统保留字如sqrt,sin)
*2,变量声明: var 变量名 : 类型
procedure TForm1.addClick(Sender: TObject); {按钮Add的事件处理过程}
var
Value , Sum : Integer; //如果有多个同类型的变量声明,只需要在变量之间用逗号隔开
Line : String; //连续多个变量声明时,不必每次都写Var,甚至有时可不写保留字Var
begin
Value := 100;
Sum := 20;
Edit1.Text := IntToStr(Value + Sum); {IntToStr函数确保赋值类型匹配}
end;
3,变量赋值:赋值语句:<变量或属性>:=<表达式或值>。(赋值号“:=”两边的数据类型应相同或兼容.)
procedure TForm1.Button1Click(Sender: TObject); begin {一个按钮onClick事件}
Edit1.Color := clRed; {控件Edit1的Color属性置为红色}
end;
Var
i : Interger = 10; //D2开始可在var块中对全局变量(非局部变量)赋初值
S : String = 'hallo world';
D : Double //且Delphi编译器自动对全局变量赋初值(整型数赋为0,浮点数赋为0.0,指针为null,字符串为空等),因此,在源代码中不必对全局变量赋零初值。
× 整型类别和实型类别都各有五种类型,同一大类别中所有的类型都相容可赋值,但如果值的范围超出变量范围内则赋意外的值(范围错误)。
× 不同大类间赋值要谨慎。一般来说,可以将一个较小范围的值赋给一个较大范围的值。例如,您可以将整型值10赋给一个接受实型值的Double属性而使得值成为10.0,但如果将一个Double类型的值赋给整形变量,则会出现类型错误。
× 打开Range Checking范围检查功能(选用Options|Project|Compiler Options Page|选择Range Checking),在库单元的Implementation后面有{$R*.DFM}字样表示范围检查打开
(4)命名约定:简单的用camelCase,复杂的用PascalCase
四,常量:
1,常量声明:用“const “和“= “说明时固定了数据类型与值。
const Pi = 3.14159; //真常量:const 常量名=常量表达式; real型常量。由于未声明常量的类型,编译器能根据常量的值自动判断常量的类型并分配内存(如同VB);对于整型常量,编译器在运行时跟踪它的值,并不对它分配内存,
const i:integer=23; //类型常量:const 常量名:类型=值;(兼容老版本,要加编译开关{$j+};现在可以直接在全局变量中赋初值)。由于指定常量的类型,就能完全控制编译器对常量的处理
2, 常量分配内存:注意编译器根据如下规则来对常量分配内存:整型数被认为是最小的Integer类型(10被认为是ShortInt,32000被认为是 SmallInt等等);字符串值被认为是char 类型或string类型(通过$H定义);浮点值被认为是extended数据类型,除非小数点位数小于4位(这种情况被当作comp类型); Integer和Char的集合类型被存储为它们自己。Object Pascal通过在应用程序的代码页存贮常量来优化数据空间
3,编译期间的函数:Object Pascal允许在const和var声明时用编译期间的函数,这些函数包括Ord( )、Chr( )、Trunc( )、Round( )、High( )、Low( )和Sizeof( )。如,Var w : Word = Sizeof(Byte);
4, 注意跟C和C++不一样,Object Pascal没有预编译。在Object Pascal中没有宏的概念,因此Object Pascal没有跟C一样的#define常量声明。虽然在Object Pascal中用$define进行条件编译,但不能用它来定义常量。在C或C++中用#define定义常量的地方在Object Pascal中用const来定义。
五,运算符和表达式:按优先级顺序排列
1,单目运算符 (最高优先级) :@ 取变量或函数的地址(返回一个指针) ,not 逻辑取反或按位取反
2,乘除及按位运算符 :* 相乘或集合交集 ,/ 浮点相除 ,div 整数相除 ,mod 取模 (整数相除的余数) ,as 程序运行阶段类型转换 (RTTI运算符) ,and 逻辑或按位求和 ,shl 按位左移 ,shr 按位右移
3,加减运算符 :+ 相加、集合并集、字符串连接或指针增加一个偏移量 ,- 相减、集合差集或指针减少一个偏移量 ,or 逻辑或按位或运算 ,xor 逻辑或按位异或运算
4,关系及比较运算符(最低优先级) := 判断是否相等 ,<> 判断是否不相等 ,< 判断是否小于 ,> 判断是否大于 ,⇐ 判断是否小于或等于,或是否是一个集合的子集 ,>= 判断是否大于或等于,或是否是一个集合的父集 ,in 判断是否是集合成员 ,is 判断对象是否类型兼容 (又一个RTTI运算符)
*对于像C + +中的+ +和- -等类似的运算符,Pascal 提供了Inc( )和Dec( )来执行相同的功能。如Inc(var),Inc(var,n)各相当于var+1,var+n
表达式
表达式是由运算符、运算对象和分隔符组成的一个序列,它表示的是一个运算。表达式中的运算对象可以是另外一个表达式。
在赋值语句中,表达式左右两边类型必须相容
一些合法的表达式:
X,Y //声明变量
@X //取变量的地址
//整型常量
Multi(x,y) //调用函数
X*Y //算术运算
X=Y //逻辑表达式
[‘a’,’b’,’c’] //集合表达式
Char(13) //强制类型转换,整型转为字符型。
六,用户自定义类型:
(二),自定义类型:用户还可以定义自己的数据类型。如枚举型、子界型、数组型、集合型、记录型、对象型等。每一个类型的名称都是由字母T开始,这并非必须的,但它是Delphi的惯例,在区别类型名和标识符时非常有用。
1,枚举型enumerated:type 类型名=(标识符1,标识符2, …标识符n);
枚举型的说明:
type
Tdays=( Sunday ,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday); //Sunday对应整型位置值/序号0,Monday序号1
定义上述枚举型的变量:
var
DayOfWeek:TDays;
2,子界类型subrange:某范围内的整形、布尔量、字符型或枚举型。
type
Thours = 0..23; //整型某范围的子界
TValidLetter = 'A' .. 'F'; //字符型的子界
TDays = ( Sunday ,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday); //枚举型子界
TWorkDay = Monday..Friday; //枚举型TDays型的子界
3, 数组类型
(1)、类型说明:type 类型名=array[有序类型] of 基类型;
(2)、数组变量定义
静态数组一维定义:arrA:array[下标..上标] of 数据类型 //arrA,arrB为定义的数组变量。
静态数组二维定义:arrB:array [下标1..上标1,下标2..上标2] of 数据类型
动态数组一维定义:arrA:array of 数据类型
动态数组二维定义:arrB:array of array of 数据类型
动态数组一维重置长度:setlength(arrA,长度);
动态数组二维重置长度:setlength(arrB,长度1,长度2);
(3)、引用以赋值
一维数组引用:arrA[n] //n为从下标至上标的一个量
二维数组引用:arrB[m,n];
unit Unit1;
interface
uses
SysUtils, //系统unit无需声明
Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm} // 包含表单声明
procedure TForm1.FormCreate(Sender: TObject);
var
singleArray : array of string; // 动态一维数组定义
multiArray : array of array of Word;
i, j : Integer;
type TCheck = array[1..10] of Double; //数组类型说明,TCheck[1]到TCheck[10]的10个Double型元素
var Check :TCheck; //数组变量的按已定义类型来定义
var Check2 : array [1..10] of Double; //静态一维数组定义,数组变量的直接定义
type TMatrix = array[1..10, 1..50] of Real; //静态二维数组定义
begin
SetLength(singleArray, 4); // 动态一维数组重置长度
SetLength(multiArray, 2, 3); //动态二维数组重置长度
//一维数组赋初值,从singleArray[0]开始
ShowMessage('一维数组 :');
for i := 0 to 3 do
begin
singleArray[i] := 'String '+IntToStr(i); //数组赋值/初始化
ShowMessage('Element '+IntToStr(i)+' = '+singleArray[i]);
end;
//多维数组赋初值
ShowMessage('多维数组 :');
for i := 0 to 1 do
for j := 0 to 2 do
begin
multiArray[i,j] := i + j; //二维数组数据初始化为0.0
ShowMessage('Element '+IntToStr(i)+','+IntToStr(j)+' = '+
IntToStr(multiArray[i,j]));
end;
end;
end.
4,字符串类型
type
MyString: string[15]; //string占用内存字节=所说明的大小+一个数组大小的字节(默认为255)=15+1=16
var
MyName: MyString; //变量定义
MyName := 'Frank.Smith'; //字符串赋值。MyName可看作一维的字符数组,所以MyName[3] = 'a'
常用字符串
String {$H+} AnsiString , {$H-} ShortString
'BORLAND' { BORLAND }
'You''ll see' { You'll see }
'' {无字符}
'Line 1'#13#10'Line 2'
'中华人民共和国'
字符串操作函数:
Concat和(+)功能相同,都可以将多个字符串组合在一起,建立一个较大的字符串;
Copy会返回一个字符串中的子字符串;
Delete在一个字符串中从一个指定位置起删除一定数目的字符;
Insert在一个字符串中插入一个字符串;
Length返回字符串的长度;
Pos返回一个子字符串在一个字符串中的位置,即索引值。
5,集合类型(set):Type 类型名= set of 有序类型;
集合类型相当于是整形、布尔型、字符型、枚举型和子界型的有序数组。常用于检查一个值是否属于一个特定集合
{在窗体上加入一个编辑框和一个按钮,清除编辑框中的文字,在其上加上Caption为“输入元音”的标签Label,并在编辑框的下方加入一个空的标签,将按钮的Default属性改为True,建立按钮的事件处理过程如下}
procedure TForm1.Button1Click(Sender:TObject);
type
Tvowels=set of Char;
var
Vowels:TVowels;
begin
Vowels := ['a','e','i','o','u'];
if Edit1.Text[1] in Vowels thenLable2.Caption := '是元音';
else
Lable2.Caption := '请再试';
end;
6,记录类型(record):相当于数据库的记录类型
type
类型名 = record
字段名1:类型1;
字段名2:类型2;
…
end;
type
TEmployee=record
Name : string[20];
YearHired:1990..2000;
Salary: Double;
Position: string[20];
end;
var
NewEmployee,PromotedEmployee:TEmployee; //变量定义
NewEmployee.Salary := 1000; //访问记录的特定字段(域,field)
with PromotedEmployee do //使用with..do语句可以给整个记录赋值
begin
Name :='';
YearHired := 1993;
Salary := 2000.00
Position := 'editor';
end;
PromptEmployee := NewEmployee; //记录的直接赋值/复制值
7,文件(file):
type
PhoneEntry = record
FirstName, LastName: string[20];
PhoneNumber: string[15];
Listed: Boolean;
end;
PhoneList = file of PhoneEntry;
8,类(class)
type
TListColumns = class(TCollection)
private
FOwner: TCustomListView;
function GetItem(Index: Integer): TListColumn;
procedure SetItem(Index: Integer; Value: TListColumn);
protected
function GetOwner: TPersistent; override;
procedure Update(Item: TCollectionItem); override;
public
constructor Create(AOwner: TCustomListView);
function Add: TListColumn;
property Owner: TCustomListView read FOwner;
property Items[Index: Integer]: TListColumn read GetItem write SetItem; default;
end; //类不能定义在函数或过程中
9,类引用类型(class reference)
Type 类引用类型名=class of 类类型;
如:
type TClass = class of TObject;
Var anyobj:Tclass;
Anyobj变量可以引用任何其他类。
类引用类型在用户要调用一个类的方法,但编译时又不知道该类的类型时非常有用。
10,接口(interface)
type 接口名 = interface (父接口)
各类中共同的方式或属性列表
end;
它体现的是多个互不相关的类之间的相同行为。
11,变体类型(variant)
变体类型与其他数据类型结合使用会产生类型的自动转换。
var
V1, V2, V3, V4, V5: Variant;
I: Integer;
D: Double;
S: string;
begin
V1 := 1; { integer value }
V2 := 1234.5678; { real value }
V3 := 'Hello world!'; { string value }
I := V1; { I = 1 (integer value) }
D := V2; { D = 1234.5678 (real value) }
S := V3; { S = 'Hello world!' (string value) }
12,指针类型(pointer)
type 指针类型名= ^类型
对字符串类型和类类型,其内部实现方式均用指针。但为方便使用,Delphi把许多运用指针的地方隐藏起来,用户在编制程序时可以不把其当作指针来处理,而让Delphi来处理容易出错的问题。
13,过程类型
type
TIntegerFunction = function: Integer;
TProcedure = procedure;
TStrProc = procedure(const S: string);
TMathFunc = function(X: Double): Double;
七,强制类型转换和类型约定
强制类型转换是一种技术,通过它能使编译器把一种类型的变量当作另一种类型。由于P a s c a l有
定义新类型的功能,因此编译器在调用一个函数时对形参和实参类型匹配的检查是严格的。因此为了
能通过编译检查,经常需要把一个变量的类型转换为另一个变量的类型。例如,假定要把一个字符类
型的值赋给一个b y t e类型的变量:
八,条件语句:
1, if语句
If 条件1 then 代码1
If 条件1 then 代码1 Else 代码2;
If 条件1 then begin 代码2; 代码3 //此处可用可不用';' end //此处不能用';' else if then 代码4 //此处不能用';' Else //默认与最靠近的if语句配对,可用begin…end包起嵌套的if语句来强迫else部分属于某一级的if语句 代码5; //此处要用';'
2,case语句
case语句适用于被判断的变量或属性是整形、字符型、枚举型或子界型时(LongInt除外)。用case语句进行逻辑跳转比编写复杂的if语句容易阅读,而且程序代码较快。
格式:
case 条件表达式 of
结果1:代码1;
结果2:代码2;
…
else:
代码3
end
{一个使用case语句的窗建立如下的事件处理过程:当Edit1部件接受到一个值,并按动“OK”按钮触发程序后,Number便被赋值为用户输入的数值。case语句根据Number的值判断该执行哪一条语句。}
procedure TForm1.Button1Click(Sender: TObject);
var
Number : Integer;
begin
Number := StrToInt(Edit1.Text);
case Number of
1,3,5,7,9: Label2.Caption := '奇数';
0,2,4,6,8: Label2.Caption := '偶数';
10..100:
begin
Label2.Caption := '在10到100之间';
Form1.Color := clBlue;
end;
else
Label2.Caption := '大于100或为负数';
end;
end;
九,循环语句
1,repeat语句
repeat
执行一段程序;
until 循环结束条件
repeat语句会重复执行一行或一段语句直到某一状态为真。语句以repeat开始,以until结束,其后跟随被判断的布尔表达式。参阅以下的例子:
i := 0;
repeat
i := i+1;
Writen(i);
until i=10;
当此语句被执行时,窗体的下方会出现1到10的数字。布尔表达式 i=10 (注意,与其他语言不同的是,“=”是关系运算符,而不能进行赋值操作)直到repeat..until程序段的结尾才会被计算,这意味着repeat语句至少会被执行一次。
2,while语句
while 布尔表达式 do 语句
while语句和repeat语句的不同之处是,它的布尔表达式在循环的开头进行判断。While保留字后面必须跟一个布尔表达式。如果该表达式的结果为真,循环被执行,否则会退出循环,执行while语句后面的程序。
下面的例子达到和上面的repeat例程达到同样的效果:
i := 0;
while i<10 dobegin
i := i+1;
writeln(i);
end;
3,for语句
格式1:
for 变量:=表达式1 to 表达式2 do 一段程序
格式2:
for 变量:=表达式1 downto 表达式2 do 一段程序
for语句的程序代码会执行一定的次数。它需要一个循环变量来控制循环次数。您需要说明一个变量,它的类型可以是整形、布尔型、字符型、枚举型或子界型。
下面的程序会显示1到5的数字,i为控制变量:
var
i : integer;
for i := 1 to 5 do
writeln(i);
以上三种循环语句。如果您知道循环要执行多少次的话,可以使用for语句。for循环执行速度快,效率比较高。如果您不知道循环要执行多少次,但至少会执行一次的话,选用repeat..until语句比较合适;当您认为程序可能一次都不执行的话,最好选用while..do语句。
十,函数与过程
函数Function和过程Procedure都是一种子程序或子程序的集合/模块,二者并无本质上的区别,只是出自不同的编程风格(c/c++属于函数型语言,pascal属于过程型语言),供不同风格的程序员选用。它们的细微差别是:函数一般有一个唯一的返回值,也可无返回值;过程一般无返回值,或者用变量参数的方式返回多个值。
如果一组语句能够完成某一功能,那么就把它定义为一个过程;如果要完成的功能是为了进行一系列处理之后返回一个值,那么就可以把它定义为一个函数
1,函数和过程的格式:函数/过程的标题 ==> 说明 ==> 程序代码
(1)函数/过程的标题
(2)说明:类型说明 =⇒ 变量说明 ==> 常量说明
(3)程序代码:由begin开始,end结束。函数可以将返回值赋给函数名称或者Result变量。
procedure TForm.Button1Click(Sender Tobject);
var {程序模块的说明部分}
Name : string;
begin {程序模块的语句部分}
Name := Edit1.Text;
Edit2.Text := 'Welcome to Delphi'+Name;
end; {程序模块结束}
function GetAverage(num:integer;total:Double) Double; // total和num为形参,即形式参数,由被调用过程或函数定义的参数
begin
GetAverage := total / num; //将返回值赋给Result变量效果一样
end;
下面是这个函数的调用方法:
InterestEarned :=GetAverage(2000,12); //2000和12为实参,即实际参数,由调用过程或函数引用的参数
2,参数:(过程和函数通过参数或全局量与外界的数据通信)
程序代码在调用一个过程或函数时,通常通过参数将数据传递到被调用的过程或函数中。最常用的参数有值参数、变量参数和常量参数3种。
(1),值参数:只声明其数据类型,调用函数不影响实参。 用于从外入内
(2),变量参数:需要以保留字var来声明,调用函数影响实参。 常用于过程从外入内再传出外多个返回值。
(3),常量参数:利用const关键字来声明,调用函数不改变形参。 用于从外入内,并确保传入值不变。
3,编码规范:过程名、函数名、形参名、形参的组合与顺序尽量有意义。
意义 |
样例与说明 |
|
前缀Set |
设置输入参数值 |
procedure SetUserName; |
前缀Get |
获取数值 |
function GetUserName:string; //函数在标题中还多了一项:返回值的类型 |
动词 |
动作 |
procedure FormatHardDrive; |
意群 |
每个单词首字母大写 |
procedure ThisIsReadableRoutineName; |
前缀a |
与类的特性或字段同名时的形参 |
procedure SomeProc(aUserName:string; aUserAge:integer); |
同一类型的形参应当归并在一起 |
procedureFoo(Param1,Param2,Param3:Imteger;Param4:string); |
|
形参按使用频率高低排列 |
考虑寄存器调用规则 |
SomeProc(aPlanet, aContinent, aCountry, aState, aCity). //输入参数位于输出参数之前。范围大的参数应当放在范围小的参数之前。 |
Sender: TObject首参 |
事件处理过程 |
procedure TForm1.addClick(Sender: TObject); |
表示不希望参数被过程所修改 |
把形参标以Const,如果是记录、数组、短字符串或接口类型的参数还可以提高编译效率 |
× 为防止命名冲突,可以连库单元名一起调用:SysUtils.FindClose(SR);或Windows.FindClose(Handle);
4,标识符的作用范围/作用域:
(1), 变量的作用域:在不同层次可以定义使用同名变量,但在同一层中1个变量只能定义1次。 同名变量在不同层次被定义时,代表不同的对象。执行内层程序时,外层的非局部变量虽然存在,却已经被屏蔽;而当程序从内层退出后,内层的局部变量就已经不 存在,只有外层的那个非局部变量仍然存在。
全局变量是在主程序中定义的变量。 对于整个程序均适用。
局部变量是在过程或函数中定义的变量。 只对定义它的过程或函数有效。
(2),标识符的作用域:一 个变量、常量、方法、类型或其他标识符的范围定义了这个标识符的活动区域。对于说明这个标识符的最小程序模块而言,此标识符是局部的。当您的应用程序在说 明一个标识符的程序模块外执行时,该标识符就不在此范围内。这意味着此时执行的程序无法访问这个标识符,只有当程序再度进入说明这个标识符的程序模块时, 才可以访问它。
(3),访问其他程序模块中说明的过程:Unit1.CalculateInterest(PrincipalInterestRate : Double);
(4),按照作用范围说明标识符
5,重载
D4引进了函数重载的概念(多个过程和函数有相同的名字,但有不同的参数列表)。所有需要重载的方法都需要声明,并用overload来指示,示例如下:
要 注意的是,一个类的方法的重载稍微有点不同,在后面的2 . 1 8 . 1节中介绍。虽然这是自Delphi1.0以来开发人员一直期望有的一个重要特性,但要记住小心使用它。有多个相同名字的过程和函数使得控制程序的执行和 调试程序更加困难,正因为这样,对于使用重载这个特性,既不要回避,也不要滥用。
6,缺省值参数
缺省值参数是在Delphi 4中被引进的(当调用有缺省值参数的过程和函数时,可以不提供参数)。为了声明一个有缺省值参数的过程或函数,在参数类型后跟一个等号和缺省值,示例如下:
procedure HasDefVal( S:string; I:Integer = 0)
HasDefVal( )过程能用下列两种方式调用。
HasDefVal('hello',26 );
第二种方式,指定一个参数S,对I则用缺省值:
HasDefVal('hello'); //对于I,使用缺省值
在使用缺省值参数时要遵循下列几条规则:
• 有缺省值的参数必须在参数列表的最后。在一个过程或函数的参数列表中,没有缺省值的参数
不能在有缺省值的参数的后面。
• 有缺省值的参数必须是有序类型、指针类型或集合类型。
• 有缺省值的参数必须是数值参数或常量参数,不能是引用(out )参数或无类型参数。
有缺省值参数的最大好处是,在向一个已存在的过程和函数增加功能时,不必关心向后兼容的问
题,例如,假定在一个单元中有一个函数为AddInts( ),它将两个数相加。
function AddInts(T1,T2: Integer): Integer;
begin
Result := I1 + I2;
end;
如果想修改这个函数的功能使它能实现三个数相加,可能感到麻烦,因为增加一个参数将导致已
经调用该函数的代码不能编译。由于有了有缺省值的参数,能扩展AddInits( )函数的功能而不必担心它
的兼容性,示例如下:
void_0function AddInts(T1,T2: Integer; I3: Integer = 0): Integer;
begin
Result := I1 + I2 + I3;
end;
参见: