1、1,第3章,Object Pascal 语言,本章要点: Syntactic elements(语法元素) Data types(数据类型) Procedures and functions(过程和函数) Classes and objects(类和对象),2,3.1 Syntactic elements(语法元素),ASCII 字符集 字母是大小写无关 空格(#32)和控制符(#0 到#31,其中#13 叫回 车符或行的结束符),基本语法元素组合成表达式、声明和命令语句。 命令语句描述算法行为,它是可执行的; 表达式是一个语法单元,它出现在命令语句中并表示一个值; 声明定义一个标志符(比如函
2、数或变量的名称),可以用在表达式或命令语句中.,3,3.1 基本语法元素,3.1.1特殊符号特殊符号是非文字和数字字符,或这类字符的 组合,它们有固定的意义。 单字符的特殊符号: # $ 组合字符特殊符号: (* (. *) .) / := = 注意:!(惊叹号)、”(双引号)、%(百分号)、?(问号)、(反斜杠)、_(下划线)、|(通道)和(破折号)不是特殊符号。,4,用来表示常量、变量、字段、类型、属性、过程、函 数、程序、单元、库以及包。 长度是255 个字符 以字母或下划线(_)开始,后面可以是字母、数字 和下划线,不包含空格、关键字不能用作标志符。,3.1.2 标志符,当一个标志符(
3、名称相同)在多个地方声明时,使用它时可能要对标志符进行限定。 限定标志符的语法为: identifier1.identifier2 例如:Form1.Button1.Click(它调用Form1 中Button1 的Click 方法),5,3.1.3 关键字,保留字,6,3.1.4 标签,标签是一个不超过4 位的阿拉伯数字序列,也就是从0 到9999,打头的0 没有意义.标签用于goto 语句中。,3.1.5 常量字符串,常量字符串(character string)也称为文字串string -literal)或串常量(string const),它由引用串(由一对单引号括起来的文字串)、控制
4、串(控制符构成的串)或这两种串的组合而构成。只有引用串可以包含分隔符。,BORLAND BORLAND Youll see Youll see 空串 一个空格 #89#111#117就相当于引用串 You,7,3.2 注释和编译器指示字,注释将被编译器忽略,除非它们用作分隔符或编译器指示字。 有以下几种方式创建注释: 由一对花括号所包含的文字构成注释 (* 由左圆括号加一个星号和一个星号加右圆括号之间的文字也构成注释*) / 由两个斜杠开始直到这一行的结束,这里的文字是注释 若$ 符紧跟在 或(* 之后,则这里的注释是编译器指示字。例如 $WARNINGS OFF 它告诉编译器不要产生警告信息
5、。,8,3.3 Expressions(表达式),表达式是一个有返回值的语句构造。比如, X 变量 X 变量地址 15 整数常量 InterestRate 变量 Calc(X,Y) 函数调用 X * Y X和Y 的乘积 Char(48) 类型转换 X = 1.5 布尔 C in Range1 布尔 not Done 布尔的否 a,b,c 集合 Z / (1 - Z) Z 和(1 - Z)的商,9,3.3.1运算符,运算符就像Object Pascal 的内置函数,它是语言的一部分。运算符包括: not * / div mod and shl shr as + - or xor = = in 和
6、is。、not 和 是一元运算符(使用一个运算数),+ 和- 或者是一元的,或者是二元的,其它所有运算符为二元运算符(使用两个运算数)。除了 运算符,它在运算数的后面(比如,P),其它一元运算符总是位于运算数的前面(比如,-B)。二元运算符位于运算数的中间(比如,A7)。一些运算符的行为因为传给它们的数据类型不同而不同。比如,not 运算符用于整数时,是对它的位进行求反运算,而对布尔类型进行逻辑非运算。这类运算符会在后面的多个分类中出现。除了 ,is 和in,其它运算可应用在Variant 类型上。,10,运算符 运算 运算数类型 返回类型 例子+ 加 整数实数 整数实数 X + Y- 减 整
7、数,实数 整数,实数 Result - 1* 乘 整数,实数 整数,实数 P * InterestRate/ 实数除 整数,实数 实数 X / 2 div 整数除 整数 整数 Total div UnitSize mod 余数 整数 整数 Y mod 6,+ 正 整数,实数 整数,实数 +7 - 负 整数,实数 整数,实数 -X,算术运算符,11,算术运算符规则,不管x 和y 的类型是什么,x/y 的结果总是扩展类型;对其它运算符,只要有一个运算数是实数类型,它的结果就是扩展类型;另外,只要有一个运算数是Int64 类型,它的结果就是Int64类型;否则,结果就是整数类型。如果一个运算数是整数
8、的子界类型,它就像整数类型一样被对待。,x div y 的值取整数,也就是取得x/y 的值,然后以0 的方向取得最近的整数。,mod 运算返回对运算数进行整数除后得到的余数。换句话说,就是x mod y = x - (x div y)*y。,若y 为0 的话,表达式x/y、x div y 和x mod y 将发生运行时错误。,12,布尔运算符,运算符 运算 运算数类型 结果类型 例子 Not 否 布尔 布尔 not (C in MySet) and 与 布尔 布尔 Done and (Total 0) Or 或 布尔 布尔 A or B Xor 异或 布尔 布尔 A xor B,x and y
9、 形式的表达式,当且仅当x 和y 都为True时,它的结果才为True。,布尔运算符规则,13,运算符 运算 运算数类型 返回类型 例子 + 并集 集合 集合 Set1 + Set2 差集 集合 集合 S T * 交集 集合 集合 S * T = 大于等于(超集) 集合 布尔 S1 = S2 = 等于 集合 布尔 S2 = MySet不等于 集合 布尔 MySet S1 In 成员关系 序数,集合 布尔 A in Set1,集合运算符,14,以下规则适用于+、 和* 运算符: 当且仅当序数(集合基础类型中的一个值)O 属于集合X 或集合Y(或同时属于X 和Y)时,O 属于X + Y;当且仅当O
10、 属于X 但不属于Y 时,O 属于X Y;当且仅当O 同时属于X 和Y时,O 属于X * Y。 +、 和* 的运算结果属于集合类型set of AB,这里A 是结果中的最小序数,B 是结果中的最大序数。 以下规则适用于=、=、 和in 运算符: ?只有当X(集合)中的每个成员也是Y(集合)中的成员时,X = W 等同于W V为真;?对于序数O 和集合S,只有当O 是S 的一个成员时,O in S 才为真。指针一样,只有当C 和D 指向同一个实例对象时,C = D 为真,否则C D 为真;当用于类 引用时,只有当C 和D 表示同一个类时,C = D 为真,否则C D 为真。,15,类运算符,as
11、 和is 运算符使用类和对象(实例)作为运算数,as 也用 于接口类型,运算符, 运算符返回一个变量、函数、过程或方法的地址,也就是说, 运算符构建一个指向运算数的 指针。下面的规则适用于 运算符:,?若X 是一个变量,X 返回X 的地址。若默认的编译器指示字$T 在起作用,则X 的类型是Pointer(通用指针);在$T+ 状态下时,X 的类型是T,这里T 是X 的类型;?若F 是一个例程(一个函数或过程),F 返回F 的入口点,F 的类型总是Pointer;?当 作用于类的方法时,必须使用类名来限定方法名。比如TMyClass.DoSomething 它指向TMyClass 的DoSome
12、thing 方法。,16,运算符优先级,运算符 优先级 ,not 第一级(最高) *,/,div,mod,and,shl,shr,as 第二级 +,or,xor 第三级 =,=,in,is 第四级(最低),17,集合构造器,语法: item1, ., itemn 这里,每个item 或者是表示集合基础类型中的一个有序值(表达式),或者是由两个点()连接起来的 一对这样的值(表达式)。若一个条目(item)是xy 的形式,它是从x 到y 范围间(包括x 和y)所有的有序值的简写。但若x 比y 大,则xy 不表示任何内容,xy是空集。集合构造器 表示空集,而x表示一个集合,它仅有的一个成员是x 值
13、。 red, green, MyColor 1, 5, 10K mod 12, 23 AZ, az, Chr(Digit + 48),18,3.3.2 类型转换,强制类型转换临时改变一个表达式的类型。 比如,Integer(A)把一个字符A 转换为一个整数。 强制类型转换的语法是 typeIdentifier(expression) 若表达式是一个变量,结果被称为变量转换;否则,结果是一个值转换。虽然它们的语法相同,但它们有不同的转换规则。,变量转换 Integer(A) 不能出现在赋值语句的左边。,值转换:占用的内存相同,可以把任何变量转换为任何类型,变量转换可出现在赋值语句的任何一边 ,同
14、时可以把变量转换为过程类型。,19,3. 4 数据类型、变量和常量,类型在本质上是一种数据的名称。当声明一个变量时,必须指定它的类型;类型决定了它的取值范围和可以进行的操作(运算)。每个表达式返回一个特定类型的值,函数也是如此;大多数函数和过程要求指定类型的参数。Object Pascal 是一种强类型语言,也就是说,它对各种数据类型加以区分,并且不总是允许你用一种数据类型替代另一种。这通常是有好处的,因为它使编译器能聪明地处理数据并且更深入地验证你地代码,可以避免产生难于调试的运行时错误。但当你需要更多灵活性的时候,也有办法可以绕过强类型限制,它们包括强制类型转换(typecasting)、
15、指针、变体类型(Variant)、记录中的变体部分(Variant parts in records)和绝对地址变量。,20,3.4.1简单类型,有序类型和实数类型,一、有序类型 整数、字符、布尔、枚举和子界类型 有次序的数值集合,除了它的第一个值以外,其它每个值都有一个唯一的前驱值;除了最后一个外,其它每个值都有一个唯一的后继值。并且,每个值都有一个序数决定它在这个类型中的位置。,对整数类型,一个值的序数为它本身的值子界类型保留它们的基础类型的序数值对其它有序类型,默认情况下,第一个值的序数为0,下一个为1,依此类推。声明一个枚举类型时,可明确地覆盖默认值。,21,1、整数类型,表示所有数字
16、的一个子集。一般整数类型是Integer 和Cardinal,22,2、字符类型,基本字符类型是AnsiChar 和WideChar。AnsiChar 是8 位字符集,它们将依照本地字符集的顺序排列,这可能是多字节的。AnsiChar 原先是根据ANSI 字符集建立的,但现在扩展为可以指定本地字符集。 WideChar 使用多于一个字节来表示每个字符。在当前实现中,WideChar 依据Unicode 字符集(要意识到它的实现将来可能会改变),使用一个字的宽度(16-bit)来存储字符。开头的256 个Unicode 字符对应于ANSI 字符。 一般字符类型是Char,它相当于AnsiChar
17、。 一个长度为1 的字符串常量,比如A,可以表示一个字符。内置函数Chr,返回一个在AnsiChar 或WideChar取值范围内任意一个整数的字符值。比如,Chr(65)返回字母A。,23,3、布尔类型,Boolean 类型的变量占据一个字节,Boolean 值由内置的常数 True 和False 来表示。,布尔表达式不能和整数或实数进行换算。所以,若X 是一个整数变量,语句 if X then .; 会产生编译错误。把这个变量强制转换为布尔类型也是不可取的,但下面的用法可以正常工作: if X 0 then .; use longer expression that returns Boo
18、lean value var OK: Boolean use Boolean variable . if X 0 then OK := True; if OK then .;,24,5、枚举类型,枚举类型定义一个有次序的值的集合,定义语法为:,type typeName = (val1, ., valn),例如: TypeTSound = (tsClick, tsClack, tsClock);Answer = (ansYes, ansNo, ansMaybe);,在声明变量时,可以直接使用(val1,valn)结构,它就像一个类型名称: var MyCard: (Club, Diamond,
19、 Heart, Spade);,但在声明了MyCard以后,就不能再同时声明以下语句了: var Card1: (Club, Diamond, Heart, Spade); 但可以这样: var Card1, Card2: (Club, Diamond, Heart, Spade);,25,6、子界类型,子界类型表示其它有序类型(称为基础类型)的一个子集:它的形式为LowHigh。这里,Low 和High是同一种有序类型的常量表达式,并且,Low 比High 要小。以上面的形式,就定义了一个子界类型,它包括Low 和High 之间的所有值。比如,若你声明枚举类型: type TColors =
20、 (Red, Blue, Green, Yellow, Orange, Purple, White, Black); 你就可以这样定义一个子界类型: type TMyColors = GreenWhite; 这里,TMyColors 就包含值Green、Yellow、Orange、Purple 和White。,26,二、实数类型,实数类型定义了一类可以用浮点表示的数字,一般实数类型为Real,在当前实现中,它相当于Double。 Currency 类型有固定的小数点,可以把在货币运算中出现的错误减到最少 Extended 类型比其它实数类型有更高的精度,但不够轻巧。当使用Extended 类型
21、创建的文件要跨平台共享时,务必小心。,27,3.4.2 字符串类型,字符串表示一个字符序列,在赋值语句和表达式中,字符串类型可以混合使用,编译器自动进行所需的转换。但对于过程或函数,当使用引用方式传递字符串时,类型必须正确。字符串可明确地被转换为其它类型的字符串。 关键字string 用起来就像一个一般类型名,例如 var S: string; 声明一个变量S,它保存字符串类型。在默认的$H+状态下,编译器把string(当它的后面没有包含数字的中括号时)解释为AnsiString;使用$H-指示字把它解释为ShortString。,28,Length 返回一个字符串的字符个数; SetLen
22、gth 设置一个字符串的长度; UpCase 函数把字符串转换为大写; Downcase函数把字符串转换为小写。 字符串比较。是比较它们对应位置上的字符大小(顺序)。对长度不等的字符串,较长字符串上多余的字符被认为较大(若前面没有比较出大小)。例如,AB比A大,零长度的字符串有最小值。 字符串索引。若S 是一个字符串变量,i 是一个整数表达式,则Si表示S 中第i 个字符(或者,严格说来,是第i 个字节)。对于ShortString 或AnsiString,Si是AnsiChar 类型;对于 WideString,Si是WideChar 类型。语句MyString2 := A; 把值A 赋给M
23、yString 的第2 个字符。,29,ShortString 可包含0 到255 个字符。它的长度能动态改变,它被静态分配256 字节的内存:第1 个字节存储串的长度,剩下的255 个字节存储字符。,2、长字符串,1、短字符串,AnsiString 类型又称为长字符串,它可以动态分配,并且长度只受内存限制。,3、宽字符串,WideString 类型是动态分配的、由16 位Unicode 字符所构成的字符串。在大多数方面,它和AnsiString相似。(注:宽字符串没有引用计数,不支持copy-on-write 机制,但支持内存动态分配。),30,该类型指向一个以0 结尾的Char 或Wide
24、Char 字符数组,const TempString: array012 of Char = Hello world!#0; var P: PChar; . P := TempString; (注:和P := TempString 相同),4、Pchar,31,3.4.3结构类型,结构类型的一个实例可包含多个值。 结构类型包括集合、数组、记录, 也包括类、类引用(class-reference)和接口类型。除了集合只能包含有序值以外, 结构类型可以包含其它的结构类型,且结构的层次不受限制。,32,一、集合,集合是同一种有序类型的值的聚集,它们包含的值没有内在的顺序,且不重复。 一个集合类型的取
25、值范围,是构成它的有序类型(称为基础类型)的幂,也就是说,集合可能的值是基础类型的所有子集,也包含空集。基础类型可能的值不要超过256 个,并且它们的序数必须在0 到255之间。任何像下面的形式: set of baseType 声明一个集合类型,这里,baseType 是一个合适的有序类型。,33,type TSomeInts = 1250; TIntSet = set of TSomeInts; 通过子界类型声明集合类型。 同样可以声明:type TIntSet = set of 1250; 声明变量: var Set1, Set2: TIntSet; 或者直接构造: var MySet:
26、 set of az;,运算符in 判断集合的成员关系: if a in MySet then . do something 每个集合类型可包含空集,用 来表示。,34,二、数组,一个数组是由相同类型的(称为基础类型)、经过索引的元素组成的聚集。因为每个元素有唯一的索引,所以,数组和集合不同,它可以包含多个相同的值。数组可以静态分配内存,也可以动态分配。,1、静态数组,静态数组类型以下面的格式声明: arrayindexType1, ., indexTypen of baseType,2、动态数组,动态数组没有固定大小和长度,相反,当你给它赋值或把它传给SetLength 函数时,它的内存被重
27、新分配。动态数组以下面的形式声明: array of baseType 调用SetLength,分配内存,35,要声明多维动态数组,使用复合array of . 结构,比如, type TMessageGrid = array of array of string; var Msgs: TMessageGrid; 声明一个二维字符串数组。要实例化这个数组,应用两个整数参数调用SetLength。比如,若I 和J 是整数变量,SetLength(Msgs,I,J),给它分配内存,4、数组类型和赋值,只有数组是相同类型时,它们才是赋值兼容。 var Int1, Int2: array110 of
28、Integer;或 type IntArray = array110 of Integer; var Int1: IntArray; Int2: IntArray; 这样:可以: Int1 :=Int2;,3、多维动态数组,36,三、记录,记录(类似于其它语言中的结构)表示不同种类的元素的集合,每个元素称为“字段”,声明记录类型时 要为每个字段指定名称和类型。声明记录的语法是 type recordTypeName = record fieldList1: type1; . fieldListn: typen; end 这里,recordTypeName 是一个有效标志符,每个type 表示一
29、种类型,每个fieldList 是一个有效标志符或用逗号隔开的标志符序列。,37,type TDateRec = record Year: Integer; Month: (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); Day: 131; end; TDateRec 包含3 个字段: 一个整数类型的Year,一个枚举类型的Month,另一个子界类型的Day。它们的行为就像变量。 在实例化时才进行内存分配: var Record1, Record2: TDateRec; 用记录名作限定符、通过字段名来访问字段,并直接赋值
30、。 Record1.Year := 1904; Record1.Month := Jun; Record1.Day := 16; 赋值:Record2 := Record1;,38,3.4.4 指针类型,语法: type pointerTypeName = type 类型PChar 表示一个指向Char 的指针,39,3.4.5过程类型,定义: Function FunctionName(Para1,Para2 :BaseType) : BaseType 访问: Var Fname Function (Para1,Para2 :BaseType) : BaseType 直接: Fname =
31、FunctionName 方法:只取过程或函数头(heading)并把procedure 或 function 后面的标志符去掉,剩下的就是过程类型的名称。,例如: type TIntegerFunction = function: Integer; var F: TIntegerFunction; F 是一个无参数、返回整数值的函数 procedure FuncProc(P: TIntegerFunction); FuncProc是一个过程,它的参数是一个无参数、返回整数值的函数,40,type TNotifyEvent = procedure(Sender: TObject) of obj
32、ect; TMainForm = class(TForm) procedure ButtonClick(Sender: TObject); . end; var MainForm: TMainForm; OnClick: TNotifyEvent 我们就可以进行下面的赋值: OnClick := MainForm.ButtonClick;,两个过程类型是兼容的:相同的调用约定, 相同类型的返回值(或没有返回值),并且具有相同数目的参数,并且相应位置上的类型也相同(参数名 无关紧要),41,3.4.6 变体类型(Variant types),它们的类型是可变的,或者在编译时它们的类型不能确定,它
33、们 可以在运行时改变类型。,所有的整数、实数、字符串、字符和布尔类型与Variant 是赋值兼容的。例如: var V1, V2, V3, V4, V5: Variant; begin V1 := 1; 整数值 V2 := 1234.5678; 实数值 V3 := Hello world!; 字符串 V4 := 1000; 字符串 V5 := V1 + V2 + V4; 实数值2235.5678 end;,表达式中的Variant Variant 数组,42,3.4.7 变量(Variables),变量是一个标志符,它的值能在运行时改变。从另一个角度看,变量是内存中某个位置的名称,你能使用这个
34、名称读取或写入内存中的这个位置。因为它们是有类型的,它们也就告诉了编译器如何解释它们存储的数据。,变量-数据的容器,声明语法为: var identifierList: type; identifierList 是由逗号隔开的有效标志符的列表,type 是任何有效类型 例如: var X, Y, Z: Double; I, J, K: Integer; Digit: 09; Okay: Boolean;,43,3.4.8 声明的常量,一、True constants(真常量),真常量是一个声明的标志符,它的值不能更改。语法: const identifier = constantExpress
35、ion,二、Constant expressions(常量表达式),常量表达式是一个表达式,编译器不用执行程序就能计算出它的值。常量表达式包括:常数、字符串常量;真常量;枚举类型的值;特殊常量True、False 和nil;以及由以上类型的元素通过运算符、类型转换和集合构造器构成的表达式。常量表达式不能包括变量、指针或函数调用。,三、资源字符串,资源字符串被当作资源链接到可执行文件或库中,因此,不用 重新编译程序就能修改它们,资源字符串的声明像真常量,除 了用resourcestring 代替const。 resourcestring CreateError = Cannot create f
36、ile %s;,44,五、数组常量 const Digits: array09 of Char = (0, 1, 2, 3,4, 5, 6, 7, 8, 9);,六、过程常量 function Calc(X, Y: Integer): Integer; begin . end; type TFunction = function(X, Y: Integer): Integer; const MyFunction: TFunction = Calc;,45,六、记录常量 type TPoint = record X, Y: Single; end; TVector = array01 of TP
37、oint; TMonth = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); TDate = record D: 131; M: TMonth; Y: 19001999; end;const Origin: TPoint = (X: 0.0; Y: 0.0); Line: TVector = (X: -3.1; Y: 1.5), (X: 5.8; Y: 3.0); SomeDay: TDate = (D: 2; M: Dec; Y: 1960);,46,3.5 过程和函数,自包含的语句块,能在程序的不同地方调用。函数在
38、在执行时能返回一个值,而过程不能。,3.5.1 声明过程和函数,过程声明 procedure procedureName(parameterList); directives; localDeclarations; begin statements end; 这里,procedureName 是任何有效标志符;statements 是一系列语句,当调用过程时它们被执行;(parameterList)、directives; 和localDeclarations 是可选的。,47,函数声明 function functionName(parameterList): returnType; dir
39、ectives; localDeclarations; begin statements end; 这里,functionName 是任何有效标志符,returnType 是任何类型,statements 是一系列语句,当调用函数时它们被执行;(parameterList)、directives; 和localDeclarations 是可选的。 函数名本身也扮演一个特殊的变量,它内置的变量Result 存储函数的返回值。 function WF: Integer; begin Result := 17; end;,48,调用约定 register、pascal、cdecl、stdcall、s
40、afecall 调用约定决定了参数被传递给例程的顺序,它们也影响从堆栈中删除参数、传递参数时寄存器的使用,以及错误和异常处理。默认的调用约定是register。 register 和pascal 调用从左到右传递参数,也就是说,最左边的参数最早被计算并传递,最右边的参数最后被计算和传递;cdecl、stdcall 和safecall 调用从右到左传递参数; 除了cdecl 调用,过程和函数在返回之前从堆栈中移除参数,而使用cdecl,当调用返回时,调用者从堆栈中移除参数; register 调用能使用多达3 个CPU 寄存器传递参数,而其它调用则全部使用堆栈传递参数; safecall 调用实
41、现了异常“防火墙”,在Windows 下,它实现了进程间COM 错误通知。 当调用外部代码时,推荐使用stdcall 和safecall。在Windows 中,系统API 使用stdcall 和safecall,49,External 声明 在声明过程或函数时,用external 指示字取代例程块,能允许你调用和程序分开编译的例程。外部例程可以来自目标文件或动态调入库(dynamically loadable library)。要调用目标文件中的例程,首先要使用$L(或$LINK)编译器指示字把目标文件链接到你的程序中。比如,在Windows 下: $L BLOCK.OBJ 声明你想调用的函数
42、和过程: procedure MoveWord(var Source, Dest; Count: Integer); external;,从库导入函数 要从一个动态调入库(DLL)导入例程,把如下格式的指示字 external stringConstant; 在Windwos 下 function SomeFunction(S: string): string; external strlib.dll; 从strlib.dll 导入一个叫做SomeFunction 的函数。,50,在导入例程时,它的名称可以和库中的名称不同。如果你这样做,在external 指示字中指定它的原始名称。 exte
43、rnal stringConstant1 name stringConstant2; 这里,第一个stringConstant 给出了库文件的名称,第二个stringConstant 是例程的原始名称。 在Windows 下:比如,下面的声明从user32.dll(Windows API 的一部分)导入一个函数。 function MessageBox(HWnd: Integer; Text, Caption: PChar; Flags: Integer): Integer; stdcall; external user32.dll name MessageBoxA; 函数的原始名称是Mess
44、ageBoxA,但导入后的名称是MessageBox。,51,重载过程和函数,使用相同的名称在一个作用域声明多个例程,这叫做重载。重载例程必须使用overload 指示字,并且它们有不同的参数列表。比如: function Divide(X, Y: Real): Real; overload; begin Result := X/Y; end; function Divide(X, Y: Integer): Integer; overload; begin Result := X mod Y; end;,52,局部声明 函数体或过程体经常以声明局部变量开始,它们用在例程的语句块中。这里也可以包
45、括常量、类型以及例程声明。局部标志符的作用域被限制在声明它的例程中。,函数和过程在它的局部声明块中包含其它函数和过程-嵌套 例程。例子: procedure DoSomething(S: string); var X, Y: Integer; procedure NestedProc(S: string); begin . end; begin NestedProc(S); end;,53,数值参数和变量参数 大多数参数是数值参数(默认)或变量参数(var)。数值参数通过数值传递,而变量参数通过引用传递。 function DoubleByValue(X: Integer): Integer;
46、 / X 是数值参数 begin X := X * 2; Result := X; end; function DoubleByRef(var X: Integer): Integer; / X 是变量参数 begin X := X * 2; Result := X; end; 这两个函数返回同样的结果,但只有第二个(DoubleByRef)能改变传给它的变量的值。,54,常量参数 一个常量参数(const)就像一个局部常量或者一个只读变量,常量参数和数值参数类似,但在过程或函数中你不能给常量参数赋值,也不能把它当作变量参数传给另一个例程。(但是,当把一个对象引用当作常量参数时,你仍然可以修改
47、对象的属性。) function CompareStr(const S1, S2: string): Integer;,数组参数 type TDigits = array110 of Integer; procedure Sort(A: TDigits);,字符串参数 type TDigits = array110 of Integer; procedure Sort(A: TDigits);,开放数组参数 function Find(A: array of Char): Integer; 声明了一个叫做Find 的函数,它接收任意长度的字符数组并返回一个整数。,55,动态数组 可以接收由字符
48、构成的任何数组,包括(但不限于)动态数组。对于必须是动态数组的参数,你需要指 定一个类型标志符: type TDynamicCharArray = array of Char; function Find(A: TDynamicCharArray): Integer;,规则: 元素的下标总是从0 开始,第一个是0,第二个是1,依此类推。标准函数Low 和High 返回0 和Length-1。SizeOf 函数返回传给例程的实际数组的大小; 它们只能通过元素进行访问,不允许给整个开放数组赋值; 它们只能被当作开放数组参数或无类型var 参数传给其它过程和函数,它们不能传给SetLength 函数; 你可以传递一个变量而不是数组,变量的类型就是开放数组的基础类型,它被当作一个长度为1 的数组。,