RTTI 和变体开放数组参数
RTTI & Variant Open Array Parameters
与问题相关。 RRUZ的答案修改后又遇到了一个问题。
我应该如何调用第二个重载方法 "SaveLog(str: string; Args: array of 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' 的重载版本。
我该怎么办?
Args
参数是一个动态数组。创建并填充一个动态数组并传递它。
您的代码无法编译,因为您试图传递一个开放数组构造函数。如果你有一个开放数组,那将是有效的,但你没有。你有一个动态数组。
您可能会使用的一个有用的技巧是定义一个接受变体开放数组和 returns 动态数组的函数。然后你可以使一个适应另一个内联。该函数将像这样声明:
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>
.
与问题
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' 的重载版本。 我该怎么办?
Args
参数是一个动态数组。创建并填充一个动态数组并传递它。
您的代码无法编译,因为您试图传递一个开放数组构造函数。如果你有一个开放数组,那将是有效的,但你没有。你有一个动态数组。
您可能会使用的一个有用的技巧是定义一个接受变体开放数组和 returns 动态数组的函数。然后你可以使一个适应另一个内联。该函数将像这样声明:
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>
.