(delphi11最新学习资料) Object Pascal 学习笔记---第5章第1节(开放式数组形参)

5.1.5 开放式数组形参

​ 对于数组的使用有一个非常特殊的场景,即用于向函数传递一个灵活的参数列表。除了直接传递数组外,本节和下一节还将解释两种特殊的语法约定。在上一段代码中的 Format 函数就是一个使用了这种约定的函数,它的第二个参数接受一个就地定义的数组值。

​ 与 C 语言(以及其他一些基于 C 语法的语言)不同,在传统的 Pascal 语言中,函数或过程总是有固定数量的参数。然而,在 Object Pascal 中,有一种方法可以使用就地定义的数组向例程传递不同数量的参数,这种技术被称为开放数组参数。

注解:从历史上看,开放数组参数早于动态数组,但如今这两种功能的工作方式非常相似,几乎无法区分。这就是为什么我在讨论动态数组后才介绍开放数组参数。

​ 定义开放式数组形参与定义类型化动态数组类型的基本相同,但以const指示符作为前缀。 这意味着您可以指定参数的类型,但不需要指出数组要有多少个该类型的元素。 下面是这样一个定义的例子,摘自OpenArray的示例:

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;

​ 您可以通过传递一个整数常量表达式的数组(其中也可以包含变量,作为用于计算表达式各部分的值)来调用该函数:

X := Sum([10, Y, 27 * I]);

​ 给定一个整数动态数组,可以直接将其传递给需要相同基本类型(本例中为整数)的开放数组形参的例程。下面是一个将完整数组作为参数传递的示例:

var
  List: array of Integer;
  X, I: Integer;
begin
  // 初始化数组
  SetLength(List, 10);
  for I := Low(List) to High(List) do
    List[I] := I * 2;
  // 使用我们的函数获取列表元素的总和
  X := Sum(List);

​ 这适用于动态数组。如果你有一个与基本类型相匹配的静态数组,你也可以将它传递给期待一个开放数组形参的函数,或者你可以调用 Slice 函数只传递现有数组的一部分(如它的第二个参数所示)。下面的代码段(也是 OpenArray 示例的一部分)展示了如何将静态数组或其一部分传递给 Sum 函数:

var
  List: array[1..10] of Integer;
  X, I: Integer;
begin
  // 初始化数组
  for I := Low(List) to High(List) do
    List[I] := I * 2;
  // 使用我们的函数获取列表元素的总和
  X := Sum(List);
  Show(X.ToString);
  // 对数组的一部分求和
  X := Sum(Slice(List, 5));
  Show(X.ToString);

可变类型的开放式数组形参

​ 除了有类型的开放数组参数外,Object Pascal语言还允许定义可变类型或无类型的开放式数组。这种特殊类型的数组的元素数量未定义,但这些元素的数据类型也是未定义的,同时还可以传递不同类型的元素。这是该语言中类型不完全安全的领域之一。。

​ 从技术上讲,您可以定义一个类型为array of const的参数,将一个具有未定义数量且元素类型不同的数组传递给函数。例如,这是Format函数的定义(我们将在第6章中了解如何使用该函数,同时已在一些演示中使用过):

function Format(const Format: string;
  const Args: array of const): string;

​ 第二个参数是一个开放式数组,它接收未定义数量的值。实际上,您可以用以下方式调用此函数:

N := 20;
S := 'Total:';
Show(Format('Total: %d', [N]));
Show(Format('Int: %d, Float: %f', [N, 12.4]));
Show(Format('%s %d', [S, N * 2]));

​ 请注意,您可以以常量、变量值或表达式的形式传递参数。声明此类函数很简单,但如何编写代码呢?如何知道参数的类型?可变类型开放式数组参数的值与 TVarRec 类型元素兼容。

注解: 不要混淆 TVarRec 记录和变量类型使用的 TVarData 记录。这两种结构的目的不同,不兼容。甚至可能的类型列表也是不同的,因为 TVarRec 可以保存 Object Pascal 数据类型,而 TVarData 可以保存 Windows OLE 数据类型。本章稍后将介绍变体(Variants)。

​ 以下是可变类型的开放式数组值和 TVarRec 记录支持的数据类型:

vtInteger           vtBoolean           vtChar
vtExtended          vtString            vtPointer
vtPChar             vtObject            vtClass
vtWideChar          vtPWideChar         vtAnsiString
vtCurrency          vtVariant           vtInterface
vtWideString        vtInt64             vtUnicodeString

​ 记录结构有一个类型字段(VType)和变体(variant)字段,您可以使用以访问实际数据。这是该结构高级用法,稍后将更多介绍。

​ 一种常见的方法是使用case语句处理您在此类调用中接收的不同类型的参数。在SumAll函数示例中,我希望能够对不同类型的值求和,将字符串转换为整数,将字符转换为相应的序数值,并将布尔值True转换为1。这段代码确实相当高级(并使用了指针解引用),所以如果现在不完全理解它也没关系:

function SumAll(const Args: array of const): Extended;
var
  I: Integer;
begin
  Result := 0;
  for I := Low(Args) to High(Args) do
    case Args[I].VType of
      vtInteger:
        Result := Result + Args[I].VInteger;
      vtBoolean:
        if Args[I].VBoolean then
          Result := Result + 1;
      vtExtended:
        Result := Result + Args[I].VExtended^;
      vtWideChar:
        Result := Result + Ord(Args[I].VWideChar);
      vtCurrency:
        Result := Result + Args[I].VCurrency^;
    end; // Case
end;

​ 我已将此函数添加到OpenArray示例中,并在以下方式调用它:

var
  X: Extended;
  Y: Integer;
begin
  Y := 10;
  X := SumAll([Y * Y, 'k', True, 10.34]);
  Show('SumAll: ' + X.ToString);
end;

​ 此调用的输出将Y的平方、K的序数值(为107)、布尔值的1以及扩展数的总和相加,结果为:

SumAll: 218.34
  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值