指向(子)方法的功能?

时间:2014-06-01 06:08:47

标签: delphi pointers delphi-7

如果你想使用方法的指针作为参数,你需要type方法function of object这样的方法 good

type TAcceptor = function(filename:string):boolean of object;
function acceptor(filename:string):boolean; 
begin 
  result := filename <> ''; 
end;

如果您想使用子方法的指针怎么办?它不起作用

procedure TForm1.Button1Click(Sender:TObject);
  function acceptor(filename:string):boolean of object;
  begin 
    result := filename <> ''; 
  end;
begin
end;

错误发生:; expected but OF found

问题:是否有子功能指针?我可以施展吗?

2 个答案:

答案 0 :(得分:7)

我不明白这是怎么回事。

http://docwiki.embarcadero.com/RADStudio/XE6/en/Procedural_Types

如果您查看method pointers部分,则明确说明无法使用嵌套过程和函数:

  

&#34;嵌套程序和函数(在其他程序中声明的例程)   例程)不能用作程序值,也不能预定义   程序和功能。&#34;

您可以使用匿名方法解决它。类似的东西:

procedure TForm1.Button1Click(Sender:TObject);
begin
  DoSomethingWithAcceptor(function(FileName: string): Boolean
  begin 
    Result := FileName <> '';
  end);
end;

答案 1 :(得分:1)

注意

我知道以下内容并非普遍适用,但它适用于所有已知的Delphi版本的Delphi。只要你意识到这一点,并在新版本中检查它的功能,它就是一个可行的黑客,IMO。


将嵌套函数传递给方法

在较旧的代码中,我用这个来做一些&#34;穷人的匿名方法&#34;:

type
  TLocal = packed record
    Code: Pointer;  // local (nested) function
    Frame: Pointer; // outer stack frame for local function
   end;

为了在方法中填充这样的局部,我编写了函数Local:

function Local(LocalFunction: Pointer): TLocal;
asm
  MOV [EDX].TLocal.Frame,EBP
  MOV [EDX].TLocal.Code,EAX
end;

在我的单元(某种通用集合)中,我写了一个函数来调用它们,传递一个参数(类型为TGeneric,在这种情况下,这里不重要,你也可以传递指针或其他一些)

// Calls local function using local closure provided, passing
// T as parameter to the local.
function CallLocal(T: TGeneric; const Local: TLocal): TGeneric;
asm 
  PUSH [EDX].TLocal.Frame
  CALL [EDX].TLocal.Code
  ADD ESP,4
end;

它的使用方式如下:

function TStdCollection.AsArray: TGenericArray;
var
  I: Integer;
  A: TGenericArray;

  procedure ToArray(E: TGeneric);
  begin
    Result[I] := E.Traits.Copy(E);
    Inc(I);
  end;

begin
  SetLength(A, Count);
  I := 0;
  ForEach(Local(@ToArray));
  Assert(I = Count);
  Result := A;
end;

嵌套函数中的代码生成元素的副本并将其存储在数组中。然后主程序将嵌套函数ToArray(及其堆栈框架)作为参数传递给ForEach,这是以这种方式实现的:

function TStdCollection.ForEach(Operation: TLocal): ICollection;
var
  Enum: IEnumerator;
  Elem: TGeneric;
begin
  Enum := GetEnumerator;
  Elem := Enum.First;
  while Elem <> nil do
  begin
    CallLocal(Elem, Operation);
    Elem := Enum.Next;
  end;
  Result := Self;
end;

这些示例显示了如何使用Locals。我希望这或多或少能回答你的问题。

注意

请注意,此代码是在Delphi 6时间帧中编写的。我知道现在有更好的选择,比如泛型和匿名方法。但如果需要与Delphi 7的兼容性,以上可能是一个解决方案。