delphi——过程与函数
2014-11-04 15:17
218 查看
例程(routine)是Pascal 的一个重要概念,例程由一系列语句组成,例程名是唯一的,通过例程名你可以多次调用它,这样程序中只需要一个例程就够了,由此避免了代码多次重复,而且代码也容易修改维护。从这个角度看,你可以认为例程是一种基本的代码封装机制。介绍完Pascal 例程的语法后,我会回过头来举例说明这个问题。
Pascal 过程与函数
Pascal中的例程有两种形式:过程和函数。理论上说,过程是你要求计算机执行的操作,函数是能返回值的计算。两者突出的不同点在于:函数能返回计算结果,即有一个返回值,而过程没有。两种类型的例程都可以带多个给定类型的参数。
不过实际上函数和过程差别不大,因为你可以调用函数完成一系列操作,跳过其返回值(用可选的出错代码或类似的东西代替返回值);也可以通过过程的参数传递计算结果(这种参数称为引用,下一部分会讲到)。
过程
函数
通过引用传递参数对有序类型、传统字符串类型及大型记录类型才有意义。实际上Delphi总是通过值来传递对象,因为Delphi对象本身就是引用。因此通过引用传递对象就没什么意义(除了极特殊的情况),因为这样相当于传递一个引用到另一个引用。Delphi 长字符串的情况略有不同,长字符串看起来象引用,但是如果你改变了该字符串的串变量,那么这个串在更新前将被拷贝下来。作为值参被传递的长字符串只在内存使用和操作速度方面才象引用,但是如果你改变了字符串的值,初始值将不受影响。相反,如果通过引用传递长字符串,那么串的初始值就可以改变。
常量参数[/code]
与C语言不同,Pascal 函数及过程的参数个数是预定的。如果参数个数预先没有确定,则需要通过开放数组来实现参数传递。
一个开放数组参数就是一个固定类型开放数组的元素。 也就是说,参数类型已定义,但是数组中的元素个数是未知数。见下例:
你可通过一个整数表达式组成的数组来调用该函数:
下面是从VCL的数学单元(Math Unit)中摘录的一系列函数:
当调用方式为Min (10, 20)时,编译器很容易就能判定你调用的是上列第一个函数,因此返回值也是个整数。
声明重载函数有两条原则:
每个例程声明后面必须添加overload 关键字。
例程间的参数个数或(和)参数类型必须不同,返回值不能用于区分各例程。
下面是ShowMsg 过程的三个重载过程。我已把它们添加到例OverDef 中(一个说明重载和确省参数的应用程序):
三个过程分别用三种不同的方法格式化字符串,然后在信息框中显示字符串。下面是三个例程的调用:
令我惊喜的是Delphi的代码参数技术与重载过程及函数结合得非常好。当你在例程名后面键入左圆括号时,窗口中会显示所有可用例程的参数列表,当你输入参数时,Delphi会根据所输入参数的类型过滤参数列表。从图6.4你可看到,当开始输入一个常量字符串时,Delphi只显示第一个参数为字符串的两个ShowMsg例程参数列表,滤掉了第一个参数为整数的例程。
确省参数
elphi 4 中添加了一个新功能,即允许你给函数的参数设定确省值,这样调用函数时该参数可以加上,也可以省略。下例把应用程序全程对象的MessageBox 方法重新包装了一下,用PChar 替代字符串,并设定两个确省值:
使用这一定义,你就可以用下面任一种方式调用过程:
Pascal 过程与函数
Pascal中的例程有两种形式:过程和函数。理论上说,过程是你要求计算机执行的操作,函数是能返回值的计算。两者突出的不同点在于:函数能返回计算结果,即有一个返回值,而过程没有。两种类型的例程都可以带多个给定类型的参数。
不过实际上函数和过程差别不大,因为你可以调用函数完成一系列操作,跳过其返回值(用可选的出错代码或类似的东西代替返回值);也可以通过过程的参数传递计算结果(这种参数称为引用,下一部分会讲到)。
过程
procedure Hello; begin ShowMessage ('Hello world!'); end;
函数
function Double2 (Value: Integer) : Integer; begin Result := Value * 2; end;
引用参数
pascal 例程的传递参数可以是值参也可以是引用参数。值参传递是缺省的参数传递方式:即将值参的拷贝压入栈中,例程使用、操纵的是栈中的拷贝值,不是原始值。当通过引用传递参数时,没有按正常方式把参数值的拷贝压栈(避免拷贝值压栈一般能加快程序执行速度),而是直接引用参数原始值,例程中的代码也同样访问原始值,这样就能在过程或函数中改变参数的值。引用参数用关键字var 标示。下面是利用引用传递参数的例子,引用参数用var关键字标示:
procedure DoubleTheValue (var Value: Integer); begin Value := Value * 2; end;在这种情况下,参数既把一个值传递给过程,又把新值返回给调用过程的代码。当你执行完以下代码时:[/code]
var X: Integer; begin X := 10; DoubleTheValue (X);x变量的值变成了20,因为过程通过引用访问了X的原始存储单元,由此改变了X的初始值。
通过引用传递参数对有序类型、传统字符串类型及大型记录类型才有意义。实际上Delphi总是通过值来传递对象,因为Delphi对象本身就是引用。因此通过引用传递对象就没什么意义(除了极特殊的情况),因为这样相当于传递一个引用到另一个引用。Delphi 长字符串的情况略有不同,长字符串看起来象引用,但是如果你改变了该字符串的串变量,那么这个串在更新前将被拷贝下来。作为值参被传递的长字符串只在内存使用和操作速度方面才象引用,但是如果你改变了字符串的值,初始值将不受影响。相反,如果通过引用传递长字符串,那么串的初始值就可以改变。
常量参数[/code]
除了引用参数外,还有一种参数叫常量参数。由于不允许在例程中给常量参数赋新值,因此编译器能优化常参的传递过程。编译器会选用一种与引用参数相似的方法编译常参(C++术语中的常量引用),但是从表面上看常参又与值参相似,因为常参初始值不受例程的影响。
function DoubleTheValue (const Value: Integer): Integer; begin Result := Value * 2; // compiler error end;
开放数组参数
与C语言不同,Pascal 函数及过程的参数个数是预定的。如果参数个数预先没有确定,则需要通过开放数组来实现参数传递。
一个开放数组参数就是一个固定类型开放数组的元素。 也就是说,参数类型已定义,但是数组中的元素个数是未知数。见下例:
function Sum (const A: array of Integer): Integer; var I: Integer; begin Result := 0; for I := Low(A) to High(A) do Result := Result + A[I]; end;上面通过High(A)获取数组的大小,注意其中函数返回值 Result的应用, Result用来存储临时值。
你可通过一个整数表达式组成的数组来调用该函数:
X := Sum ([10, Y, 27*I]);
类型变化的开放数组参数
什么是方法?
如果你使用过Delphi 或读过Delphi 手册,大概已经听说过“方法”这个术语。方法是一种特殊的函数或过程,它与类这一数据类型相对应。在Delphi 中,每处理一个事件,都需要定义一个方法,该方法通常是个过程。不过一般“方法”是指与类相关的函数和过程。你已经在本章和前几章中看到了几个方法。下面是Delphi 自动添加到窗体源代码中的一个空方法:procedure TForm1.Button1Click(Sender: TObject); begin {here goes your code} end;
函数重载
下面是从VCL的数学单元(Math Unit)中摘录的一系列函数:
function Min (A,B: Integer): Integer; overload; function Min (A,B: Int64): Int64; overload; function Min (A,B: Single): Single; overload; function Min (A,B: Double): Double; overload; function Min (A,B: Extended): Extended; overload;
当调用方式为Min (10, 20)时,编译器很容易就能判定你调用的是上列第一个函数,因此返回值也是个整数。
声明重载函数有两条原则:
每个例程声明后面必须添加overload 关键字。
例程间的参数个数或(和)参数类型必须不同,返回值不能用于区分各例程。
下面是ShowMsg 过程的三个重载过程。我已把它们添加到例OverDef 中(一个说明重载和确省参数的应用程序):
procedure ShowMsg (str: string); overload; begin MessageDlg (str, mtInformation, [mbOK], 0); end; procedure ShowMsg (FormatStr: string; Params: array of const); overload; begin MessageDlg (Format (FormatStr, Params), mtInformation, [mbOK], 0); end; procedure ShowMsg (I: Integer; Str: string); overload; begin ShowMsg (IntToStr (I) + ' ' + Str); end;
三个过程分别用三种不同的方法格式化字符串,然后在信息框中显示字符串。下面是三个例程的调用:
ShowMsg ('Hello'); ShowMsg ('Total = %d.', [100]); ShowMsg (10, 'MBytes');
令我惊喜的是Delphi的代码参数技术与重载过程及函数结合得非常好。当你在例程名后面键入左圆括号时,窗口中会显示所有可用例程的参数列表,当你输入参数时,Delphi会根据所输入参数的类型过滤参数列表。从图6.4你可看到,当开始输入一个常量字符串时,Delphi只显示第一个参数为字符串的两个ShowMsg例程参数列表,滤掉了第一个参数为整数的例程。
确省参数
elphi 4 中添加了一个新功能,即允许你给函数的参数设定确省值,这样调用函数时该参数可以加上,也可以省略。下例把应用程序全程对象的MessageBox 方法重新包装了一下,用PChar 替代字符串,并设定两个确省值:
procedure MessBox (Msg: string; Caption: string = 'Warning'; Flags: LongInt = mb_OK or mb_IconHand); begin Application.MessageBox (PChar (Msg), PChar (Caption), Flags); end;
使用这一定义,你就可以用下面任一种方式调用过程:
MessBox ('Something wrong here!'); MessBox ('Something wrong here!', 'Attention'); MessBox ('Hello', 'Message', mb_OK);
相关文章推荐
- [原创]如何在Delphi中调用.Net编写的DLL中的函数(Function)、过程(Procedure)
- 初学 Delphi 嵌入汇编[4] - 寄存器在过程与函数中的使用
- 浅谈Delphi过程与函数01 - 零基础入门学习Delphi20
- 浅谈Delphi过程与函数03 - 零基础入门学习Delphi22
- 浅谈Delphi过程与函数03 - 零基础入门学习Delphi22
- [原创]如何在Delphi中调用.Net编写的DLL中的函数(Function)、过程(Procedure)
- DELPHI学习---过程和函数
- Delphi过程函数传递参数的几种方式
- Delphi 函数指针 过程/函数类型
- Delphi 函数指针 过程/函数类型
- 初学 Delphi 嵌入汇编[5] - 寄存器在过程与函数中的使用 - 续
- Delphi语句、过程函数
- 关于Delphi过程或者函数的参数时,有var与无var的区别
- Delphi 过程 和 函数 的基本实例
- Delphi初浅入门笔记之四:过程与函数(函数篇)
- 如何在Delphi中调用.Net编写的DLL中的函数(Function)、过程(Procedure)
- delphi多线程的入口函数也可以是一个过程
- Delphi 2010学习笔记(18)---函数与过程---2011-01-21
- 浅谈Delphi过程与函数02 - 零基础入门学习Delphi21
- Delphi 函数指针 过程/函数类型