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

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

編輯:Delphi

五、完整代碼

{******************************************************
*
* Delphi Smart Pointer class
* AutoPtr
* Version 0.2 beta
* Yang Qinqing @ http://www.cnblogs.com/felixyeou
*
*******************************************************}
unit AutoPtr;
interface
uses
SysUtils,
TypInfo;
type
IAutoPtr<T> = interface
['{86DB82D6-9A32-4A6A-9191-2E0DFE083C38}']
function Get: T;
function Release: T;
procedure Reset(aObj: T);
end;
TAutoPtr<T> = class(TInterfacedObject, IAutoPtr<T>)
private
fObj: T;
fTypeInfo: PTypeInfo;
procedure FreeObj;
public
class function New(aObj: T): IAutoPtr<T>; overload;
class function New: IAutoPtr<T>; overload;
constructor Create(aObj: T); virtual;
destructor Destroy; override;
function Get: T;
function Release: T;
procedure Reset(aObj: T);
end;
implementation
{ TAutoPtr<T> }
constructor TAutoPtr<T>.Create(aObj: T);
begin
fObj := aObj;
// 獲取泛型的類型
fTypeInfo := TypeInfo(T);
end;
class function TAutoPtr<T>.New(aObj: T): IAutoPtr<T>;
begin
Result := TAutoPtr<T>.Create(aObj) as IAutoPtr<T>;
end;
function TAutoPtr<T>.Release: T;
begin
Result := fObj;
// fObj := nil
Integer((@fObj)^) := 0;
end;
procedure TAutoPtr<T>.Reset(aObj: T);
begin
// aObj <> fObj then
if Integer((@aObj)^) <> Integer((@fObj)^) then
begin
FreeObj;
fObj := aObj;
end;
end;
destructor TAutoPtr<T>.Destroy;
begin
// if fObj = nil then..
if Integer((@fObj)^) <> 0 then
FreeObj;
fTypeInfo := nil;
inherited;
end;
procedure TAutoPtr<T>.FreeObj;
begin
// 此處如果TypeInfo為空,則說明T為Pointer
// 此處只要簡單的釋放內存即可
if fTypeInfo = nil then
//FreeMem(Pointer((@fObj)^))
// 此處應該調用Dispose,因為Dispose內部已經實現FreeMem:
// PUSH EAX
// CALL _Finalize
// POP EAX
// CALL _FreeMem
Dispose(Pointer((@fObj)^))
else
begin
case fTypeInfo.Kind of
tkClass:
// 調用Object.Free,進而調用Destructor Dispose(virtual)方法
// 實現在對象樹上的遍歷釋放
TObject((@fObj)^).Free;
tkArray, tkDynArray:
// 數組和動態數組無需釋放
end;
end;
// fobj := nil;
Integer((@fObj)^) := 0;
end;
function TAutoPtr<T>.Get: T;
begin
Result := fObj;
end;
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;
end.
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved