智能指针(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=interface
    ['{86DB82D6-9A32-4A6A-9191-2E0DFE083C38}']
    functionGet:T;
    functionRelease:T;
    procedureReset(aObj:T);
  end;
  TAutoPtr=class(TInterfacedObject,IAutoPtr)
  private
     fObj:T;
    fTypeInfo:PTypeInfo;
    procedureFreeObj;
  public
     classfunctionNew(aObj:T):IAutoPtr;overload;
    classfunctionNew:IAutoPtr;overload;
     constructorCreate(aObj:T);virtual;
     destructorDestroy;override;
    functionGet:T;
    functionRelease:T;
    procedureReset(aObj:T);
  end;
implementation
{TAutoPtr}
constructorTAutoPtr.Create(aObj:T);
begin
  fObj:=aObj;
  //获取泛型的类型
  fTypeInfo:=TypeInfo(T);
end;
classfunctionTAutoPtr.New(aObj:T):IAutoPtr;
begin
  Result:=TAutoPtr.Create(aObj)asIAutoPtr;
end;
functionTAutoPtr.Release:T;
begin
  Result:=fObj;
  //fObj:=nil
  Integer((@fObj)^):=0;
end;
procedureTAutoPtr.Reset(aObj:T);
begin
  //aObj<>fObjthen
  ifInteger((@aObj)^)<>Integer((@fObj)^)then
  begin
    FreeObj;
    fObj:=aObj;
  end;
end;
destructorTAutoPtr.Destroy;
begin
  //iffObj=nilthen..
  ifInteger((@fObj)^)<>0then
    FreeObj;
  fTypeInfo:=nil;
  inherited;
end;
procedureTAutoPtr.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.Get:T;
begin
  Result:=fObj;
end;
classfunctionTAutoPtr.New:IAutoPtr;
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;

你可能感兴趣的:(DELPHI)