Is there a non-reference-counted base class like T

2019-03-18 00:37发布

I need a base class like TInterfacedObject but without reference counting (so a kind of TNonRefCountedInterfacedObject).

This actually is the nth time I need such a class and somehow I always end up writing (read: copy and pasting) my own again and again. I cannot believe that there is no "official" base class I can use.

Is there a base class somewhere in the RTL implementing IInterface but without reference counting which I can derive my classes from?

5条回答
Summer. ? 凉城
2楼-- · 2019-03-18 00:49

You might consider TInterfacedPersistent. If you don't override GetOwner it does no ref-counting.

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-03-18 00:50

In the unit Generics.Defaults there is a class TSingletonImplementation defined. Available in Delphi 2009 and above.

  // 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;
查看更多
萌系小妹纸
4楼-- · 2019-03-18 00:51

I don't know of any out-of-the-box base class, so I wrote my own (like you). Just put it in a common utils unit and you are done.

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;
查看更多
该账号已被封号
5楼-- · 2019-03-18 00:53

I did this. It can be used in place of TInterfacedObject with or without reference counting. It also has a name property - very useful when debugging.

// 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;


// =============================================================================
查看更多
霸刀☆藐视天下
6楼-- · 2019-03-18 00:57

There is no such class, but you can easily write your own, as others have shown. I do, however, wonder why you would need it. In my experience, there is seldom a real need for such a class, even if you want to mix object and interface references.

Also note that when you use such a class, you'll still have to take care of setting any interface references you have to such an object to nil before they leave scope and before you free the object. Otherwise you might get the situation the runtime tries to call _Release on a freed object, and that tends to cause an invalid pointer exception.

IOW, I would advise against using such a class at all.

查看更多
登录 后发表回答