2010-09-24 39 views
3

这里是我的代码示例:如何从Delphi中的子类获取指向基类中方法的指针?

type 
    TMyBaseClass = class 
    public 
    procedure SomeProc; virtual; 
    end; 

    TMyChildClass = class(TMyBaseClass) 
    public 
    procedure SomeProc; override; 
    end; 

var 
    SomeDelegate: procedure of object; 

procedure TMyBaseClass.SomeProc; 
begin 
    ShowMessage('Base proc'); 
end; 

procedure TMyChildClass.SomeProc; 
begin 
    ShowMessage('Child proc'); 
    // here i want to get a pointer to TMyBaseClass.SomeProc (NOT IN THIS CLASS!): 
    SomeDelegate := SomeProc; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    with TMyChildClass.Create do 
    try 
    // there will be "Child proc" message: 
    SomeProc; 
    finally 
    Free; 
    end; 
    // there i want to get "Base proc" message, but i get "Child proc" again 
    // (but it is destroyed anyway, how coud it be?): 
    SomeDelegate; 
end; 

回答

8

我所知道的一个方法是:

procedure TMyChildClass.BaseSomeProc; 
begin 
    inherited SomeProc; 
end; 


procedure TMyChildClass.SomeProc; 
begin 
    ShowMessage('Child proc'); 
    SomeDelegate := BaseSomeProc; 
end; 

的第二点是改变SomeProc声明从overridereintroduce

TMyChildClass = class(TMyBaseClass) 
public 
    procedure SomeProc; reintroduce; 
end; 

,然后投selfTMyBaseClass(不要用as剧组):

SomeDelegate := TMyBaseClass(self).SomeProc; 

另请注意,您的代码会因为您在已经释放的对象上调用SomeDelegate而导致访问冲突。

+0

谢谢!你的第一种方法正是我想要的=) – SomeOne 2010-09-24 06:23:16

+1

请注意Michal Niklas对违反访问权限的说法。你仍然会得到一个,即使是“继承”。这是因为你不能有一个指向CLASS方法的指针(除非它被声明为“class procedure”),只能用于OBJECT的方法。当你调用Free()时,你的对象被销毁,并且任何对它的引用,包括SomeDelegate(包含对它的函数的引用)都不再有效。 – himself 2010-09-24 11:54:13

+0

当我尝试使用我的Turbo Delphi代码时,出现访问冲突异常。 – 2010-09-24 12:09:36

4

添加一个类型声明和一些类型转换工作,但带有一些警告提示。如你自己提到过的,在实例被释放后调用somedelegate并不AV。这是因为你的SomeProc方法不使用任何实例变量,它只是调用ShowMessage。

如果您将任何实例变量添加到调用中,如果内存未被重新分配,您甚至可能会逃脱。这将是一个等待发生的AV。

底线:

  • 不调用方法关闭损坏的对象。
  • 在类的一个实例中设置一个全局变量,该类在类的整个生命周期中仍然存在不被认为是良好的设计。
  • 在一个理想的设计中,除了通过调用继承之外,应该不需要子类将某个调用返回给祖先的方法。

代码更改

... 
type 
    TSomeDelegate = procedure of object; 

var 
    SomeDelegate: TSomeDelegate; 

... 

procedure TMyChildClass.SomeProc; 
var 
    method: TMethod; 
begin 
    ShowMessage('Child proc'); 
    // here i want to get a pointer to TMyBaseClass.SomeProc (NOT IN THIS CLASS!): 
    method.Code := @TMyBaseClass.SomeProc; 
    method.Data := Self; 
    SomeDelegate := TSomeDelegate(method); 
end; 
相关问题