2010-10-28 44 views
4

將類層次結構的祖先從TObject更改爲TInterfacedObject是否有任何副作用,以便我可以在繼承鏈下面實現接口?在Delphi中將接口引入到現有的類層次結構中

我在Delphi中編寫了幾年,但從未遇到過接口。我習慣於用其他語言來使用它們。現在我又參與了一個Delphi項目,我想開始利用它們,但我知道它們的工作方式與Java或C#中的有所不同。

回答

4

如果您已經有使用該類的現有代碼,您可能必須對其進行大量修改以保留對接口的引用,而不是對象實例。接口是自動引用計數和釋放的,因此,對實現者實例的任何引用都將成爲無效指針。

+0

在大多數情況下,對象在單個函數中創建和銷燬。我主要擔心的是計數引用是否會干擾手動內存管理。它是一個龐大的代碼庫,只有很少的單元測試,因此我計劃逐步替換引用。 – 2010-10-28 16:43:13

+2

@codeelegance:是的,接口計數取代手動內存管理。您可以在任何給定的對象上使用其中一種,但不能同時使用這兩種。 – 2010-10-28 16:48:35

+0

@Mason所以只要我沒有對象引用和指向同一對象的接口引用,我應該沒問題? – 2010-10-28 16:54:41

1

除了實例大小中的一些額外的字節,沒有。這可能是最好的方式。

3

只要您繼承層次結構頂部(底部?)的類,就可以正常工作。這段代碼可以確保你的新類不會自由釋放 - 就像TInterfaceObject的默認行爲一樣 - 你可能已經自己釋放了它們並且想保留這些。這個活動實際上正是VCL中TComponent所做的 - 它支持接口,但沒有引用計數。

type 


    TYourAncestor = class(TInterfacedObject) 
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; 
    function _AddRef: Integer; stdcall; 
    function _Release: Integer; stdcall; 

    end; 



implementation 



function TYourAncestor.QueryInterface(const IID: TGUID; out Obj): HResult; 
const 
    E_NOINTERFACE = HResult($80004002); 
begin 
    if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE; 
end; 


function TYourAncestor._AddRef: Integer; 
begin 
    Result := -1 // -1 indicates no reference counting is taking place 
end; 

function TYourAncestor._Release: Integer; 
begin 
    Result := -1 // -1 indicates no reference counting is taking place 
end; 
+0

比方說,我沒有重新實現這三個函數,並嘗試從接口引用中手動釋放一個對象。結果會是什麼? – 2010-10-28 16:53:03

+0

@codeelegance:結果將是編譯器錯誤,不可能從接口引用中釋放對象。 – mjn 2010-10-28 17:49:10

+0

這裏你不需要從TInterfacedObject繼承,實現IUnknown的TObject會很好。 – tomazy 2010-10-28 19:42:18