是否有像TInterfacedObject这样的非引用计数基类?

时间:2011-08-16 14:50:57

标签: delphi interface delphi-xe reference-counting

我需要一个像TInterfacedObject这样的基类但没有引用计数(所以有一种TNonRefCountedInterfacedObject)。

这实际上是第n次我需要这样一个课程,不知怎的,我总是一次又一次地写作(阅读:复制和粘贴)我自己。我无法相信我没有“官方”基类可以使用。

在实现IInterface的RTL中是否存在基类但没有引用计数我可以从中派生出类?

5 个答案:

答案 0 :(得分:16)

在Generics.Defaults单元中,定义了一个类TSingletonImplementation。适用于Delphi 2009及更高版本。

  // A non-reference-counted IInterface implementation.
  TSingletonImplementation = class(TObject, IInterface)
  protected
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
  end;

答案 1 :(得分:3)

我这样做了。它可以代替TInterfacedObject使用或不使用引用计数。它还有一个名称属性 - 在调试时非常有用。

// TArtInterfacedObject
// =============================================================================


// An object that supports interfaces, allowing naming and optional reference counting
type
  TArtInterfacedObject = class( TInterfacedObject )
    constructor Create( AReferenceCounted : boolean = True);
  PRIVATE
    FName             : string;
    FReferenceCounted : boolean;
  PROTECTED
    procedure SetName( const AName : string ); virtual;
  PUBLIC

    property Name : string
               read FName
               write SetName;

    function QueryInterface(const AGUID : TGUID; out Obj): HResult; stdcall;
    function SupportsInterface( const AGUID : TGUID ) : boolean;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

  end;

// =============================================================================




{ TArtInterfacedObject }

constructor TArtInterfacedObject.Create( AReferenceCounted : boolean = True);
begin
  inherited Create;

  FName := '';

  FReferenceCounted := AReferenceCounted;
end;

function TArtInterfacedObject.QueryInterface(const AGUID: TGUID; out Obj): HResult;
const
  E_NOINTERFACE = HResult($80004002);
begin
  If FReferenceCounted then
    Result := inherited QueryInterface( AGUID, Obj )
   else
    if GetInterface(AGUID, Obj) then Result := 0 else Result := E_NOINTERFACE;
end;


procedure TArtInterfacedObject.SetName(const AName: string);
begin
  FName := AName;
end;

function TArtInterfacedObject.SupportsInterface(
  const AGUID: TGUID): boolean;
var
  P : TObject;
begin
  Result := QueryInterface( AGUID, P ) = S_OK;
end;


function TArtInterfacedObject._AddRef: Integer;
begin
  If FReferenceCounted then
    Result := inherited _AddRef
   else
    Result := -1   // -1 indicates no reference counting is taking place
end;

function TArtInterfacedObject._Release: Integer;
begin
  If FReferenceCounted then
    Result := inherited _Release
   else
    Result := -1   // -1 indicates no reference counting is taking place
end;


// =============================================================================

答案 2 :(得分:3)

您可以考虑TInterfacedPersistent。如果你没有覆盖GetOwner,它就不会重新计数。

答案 3 :(得分:1)

我不知道任何开箱即用的基类,所以我写了自己的(像你一样)。只需将它放在一个通用的utils单元中就可以了。

type
  TPureInterfacedObject = class(TObject, IInterface)
  protected
    { IInterface }
    function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
  end;

{ TPureInterfacedObject }

function TPureInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
  Result := E_NOINTERFACE;
end;

function TPureInterfacedObject._AddRef: Integer;
begin
  Result := -1;
end;

function TPureInterfacedObject._Release: Integer;
begin
  Result := -1;
end;

答案 4 :(得分:1)

没有这样的课程,但你可以轻松地编写自己的课程,正如其他人所表明的那样。但是,我确实想知道你为什么需要它。根据我的经验,即使你想混合对象和接口引用,也很少真正需要这样的类。

另请注意,当您使用这样的类时,您仍然必须在离开作用域之前和释放对象之前,将对此类对象的任何接口引用设置为nil。否则,您可能会遇到运行时尝试在释放的对象上调用_Release的情况,这往往会导致无效的指针异常。

IOW,我会建议 反对 使用这样的课程。

相关问题