智能指針(Smart Pointer)的實現

{******************************************************
*
* Delphi Smart Pointer class
* AutoPtr
* Version 0.2 beta
* Yang Qinqing @ http://www.cnblogs.com/felixyeou
*
*******************************************************}
unitAutoPtr;
interface
uses
  SysUtils,
  TypInfo;
type
  IAutoPtr<T>=interface
    ['{86DB82D6-9A32-4A6A-9191-2E0DFE083C38}']
    functionGet:T;
    functionRelease:T;
    procedureReset(aObj:T);
  end;
  TAutoPtr<T>=class(TInterfacedObject,IAutoPtr<T>)
  private
     fObj:T;
    fTypeInfo:PTypeInfo;
    procedureFreeObj;
  public
     classfunctionNew(aObj:T):IAutoPtr<T>;overload;
    classfunctionNew:IAutoPtr<T>;overload;
     constructorCreate(aObj:T);virtual;
     destructorDestroy;override;
    functionGet:T;
    functionRelease:T;
    procedureReset(aObj:T);
  end;
implementation
{TAutoPtr<T>}
constructorTAutoPtr<T>.Create(aObj:T);
begin
  fObj:=aObj;
  //獲取泛型的類型
  fTypeInfo:=TypeInfo(T);
end;
classfunctionTAutoPtr<T>.New(aObj:T):IAutoPtr<T>;
begin
  Result:=TAutoPtr<T>.Create(aObj)asIAutoPtr<T>;
end;
functionTAutoPtr<T>.Release:T;
begin
  Result:=fObj;
  //fObj:=nil
  Integer((@fObj)^):=0;
end;
procedureTAutoPtr<T>.Reset(aObj:T);
begin
  //aObj<>fObjthen
  ifInteger((@aObj)^)<>Integer((@fObj)^)then
  begin
    FreeObj;
    fObj:=aObj;
  end;
end;
destructorTAutoPtr<T>.Destroy;
begin
  //iffObj=nilthen..
  ifInteger((@fObj)^)<>0then
    FreeObj;
  fTypeInfo:=nil;
  inherited;
end;
procedureTAutoPtr<T>.FreeObj;
begin
  //此處如果TypeInfo爲空,則說明T爲Pointer
  //此處只要簡單的釋放內存即可
  iffTypeInfo=nilthen
    //FreeMem(Pointer((@fObj)^))
    //此處應該調用Dispose,因爲Dispose內部已經實現FreeMem:
    //PUSH  EAX
    //CALL  _Finalize
    //POP  EAX
    //CALL  _FreeMem
    Dispose(Pointer((@fObj)^))
  else
  begin
    casefTypeInfo.Kindof
      tkClass:
        //調用Object.Free,進而調用DestructorDispose(virtual)方法
        //實現在對象樹上的遍歷釋放
        TObject((@fObj)^).Free;
      tkArray,tkDynArray:
        //數組和動態數組無需釋放
    end;
  end;
  //fobj:=nil;
  Integer((@fObj)^):=0;
end;
functionTAutoPtr<T>.Get:T;
begin
  Result:=fObj;
end;
classfunctionTAutoPtr<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;
  raiseException.Create('只能構造class型的對象。');
end;

發佈了2 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章