delphi——过程与函数

例程(routine)是Pascal 的一个重要概念,例程由一系列语句组成,例程名是唯一的,通过例程名你可以多次调用它,这样程序中只需要一个例程就够了,由此避免了代码多次重复,而且代码也容易修改维护。从这个角度看,你可以认为例程是一种基本的代码封装机制。介绍完Pascal 例程的语法后,我会回过头来举例说明这个问题。


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;
在这种情况下,参数既把一个值传递给过程,又把新值返回给调用过程的代码。当你执行完以下代码时:
var
  X: Integer;
begin
  X := 10;
  DoubleTheValue (X);
x变量的值变成了20,因为过程通过引用访问了X的原始存储单元,由此改变了X的初始值。

通过引用传递参数对有序类型、传统字符串类型及大型记录类型才有意义。实际上Delphi总是通过值来传递对象,因为Delphi对象本身就是引用。因此通过引用传递对象就没什么意义(除了极特殊的情况),因为这样相当于传递一个引用到另一个引用。

Delphi 长字符串的情况略有不同,长字符串看起来象引用,但是如果你改变了该字符串的串变量,那么这个串在更新前将被拷贝下来。作为值参被传递的长字符串只在内存使用和操作速度方面才象引用,但是如果你改变了字符串的值,初始值将不受影响。相反,如果通过引用传递长字符串,那么串的初始值就可以改变。


常量参数
除了引用参数外,还有一种参数叫常量参数。由于不允许在例程中给常量参数赋新值,因此编译器能优化常参的传递过程。编译器会选用一种与引用参数相似的方法编译常参(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);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值