程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi2009初體驗 - 語言篇 - 智能指針(Smart Pointer)的實現(二)(3)

Delphi2009初體驗 - 語言篇 - 智能指針(Smart Pointer)的實現(二)(3)

編輯:Delphi

而_Finalize方法是做對有類型的指針(如:PGUID)所指向的結構體變量的一些“善後工作”,如果為純Pointer,_Finalize方法內將不執行:

asm
{ ECX number of elements of that type }
CMP ECX, 0 { no array -> nop }
JE @@zerolength
...
@@zerolength:
end;

所以,我們就可以放心的使用Dispose方法了:

if fTypeInfo = nil then
//FreeMem(Pointer((@fObj)^))
// 此處應該調用Dispose,因為Dispose內部已經實現FreeMem:
// PUSH EAX
// CALL _Finalize
// POP EAX
// CALL _FreeMem
Dispose(Pointer((@fObj)^));

四、改進New方法

在方法New中,我們將指針傳入智能指針內部,由智能指針來管理指針的自動釋放。在翻譯Java的JSon-RPC的時候,為了實現類似於Java的垃圾回收功能,我使用到了智能指針。當翻譯到JSONObject的時候,我發現New方法非常的麻煩:

fMyHashMap:=TAutoPtr<TDictionary<string,IAutoPtr<TObject>>>.New(TDictionary<string,IAutoPtr<TObject>>.Create);

我已經告訴TAutoPtr<T>,T的類型為TDictionary<string,IAutoPtr<TObject>>,我能不能寫一個New的重載方法,讓它自動實現對T的創建呢?如果T的約束為T: class或T: constructor,則很好實現:T.Create即可。現在,T沒有任何約束,如果加了T.Create編譯器是不支持的。我研究出了一種可行的方法,代碼如下:

class function TAutoPtr<T>.New: IAutoPtr<T>;
var
typInfo: PTypeInfo;
obj: TObject;
objNew: T;
begin
typInfo := TypeInfo(T);
// 在此處只能創建class型的指針,不能創建無類型指針
// 因為指針在Delphi中有兩種初始化方式
// 1、GetMem(p, 100);
// 2、New(p);
if (typInfo <> nil) and (typInfo.Kind = tkClass) then
begin
// 獲取T的類型並調用默認構造函數創建對象
obj := GetTypeData(typInfo).ClassType.Create;
// 使用以下方法強制轉換
objNew := T((@obj)^);
Exit(New(objNew));
end;
raise Exception.Create('只能構造class型的對象。');
end;

原理在代碼的注釋中寫得很清楚了,這裡只能針對class型的類型做構造,Pointer型的類型會拋出異

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved