RTTI&变体开放数组参数

时间:2015-01-06 07:24:25

标签: delphi delphi-xe3

与问题TVirtualMethodInterceptor.Create doesn't support the class that has overload virtual method.相关。在修改RRUZ的答案后,我又遇到了另一个问题。 我应该如何调用第二个重载方法“SaveLog(str:string; Args:TConst数组);” 。 如下代码

type

  TConst = array of TVarRec;

  TLog = class
  public
    constructor Create();

    procedure SaveLog(str: string); overload; virtual;
    procedure SaveLog(str: string; Args: TConst); overload;  virtual;
  end;

constructor TLog.Create(str: string);
begin

end;

procedure TLog.SaveLog(str: string);
begin
  MessageBox(GetFocus(), PChar(str), 'Test Message', MB_OK);
end;

procedure TLog.SaveLog(str: string; Args: TConst);
var
  buf: string;

begin
  buf:=Format(str, Args);
  SaveLog(buf);
end;


procedure MyTest(nID: Integer);
var
  ttt: TLog;
  vmi: TVirtualMethodInterceptor;

begin
  ttt:=TLog.Create();
  try
    ttt.SaveLog('ID = %d', [nID]);
    vmi:=TVirtualMethodInterceptor.Create(ttt.ClassType);
    try
      //
    finally
      vmi.Free();
    end;
  finally
    ttt.Free();
  end;
end;

代码“ttt.SaveLog('ID =%d',[nID]);”将获得 编译器错误:E2250没有可以使用这些参数调用的'SaveLog'的重载版本。 我该怎么办?

1 个答案:

答案 0 :(得分:1)

Args参数是动态数组。创建并填充动态数组并传递它。

您的代码无法编译,因为您尝试传递打开的数组构造函数。如果你有一个开放阵列,这将是有效的,但你不是。你有一个动态数组。

您可能使用的一个有用技巧是定义一个接受变量开放数组并返回动态数组的函数。然后你可以将一个内联到另一个内联。该函数将声明如下:

function VariantOpenArrayToDynArray(const Args: array of const): TArray<TVarRec>;

请注意,我更喜欢使用通用动态数组TArray<T>而不是TConst。这样做有更好的类型兼容性的好处。

Rudy Velthuis详细介绍了这一点,并展示了如何在本文中实现适配器功能:Open array parameters and array of const


尽管如此,TVarRec并非专为明确使用而设计。它是变体开放数组的运行时支持。正如Rudy的文章所示,一旦你离开编译器支持变体开放数组的安全范围,它需要一些明确的内存管理。我不建议使用TArray<TVarRec>

相反,我建议你使用现代变体类型,这种类型是为新式RTTI设计的。那是TValue。此变体类型专为显式使用而设计,并自动执行内存管理。使用TArray<TValue>而不是TArray<TVarRec>