2010-09-24 75 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; 
相關問題