http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1312
В процессе обсуждения, как мне кажется, родилось решение, которое может быть использовано для своих классов, которые должны реализовать интерфейс, однако управление временем жизни объектов должно быть ручное. Вот класс, от которого в таком случае можно унаследоваться:
TMyInterfacedObject = class(TObject, IInterface)
protected
FRefCount: Integer;
FDestroyed: Boolean;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
procedure FreeInstance; override;
end;
procedure TMyInterfacedObject.FreeInstance;
begin
FDestroyed := True;
if RefCount = 0 then
inherited FreeInstance;
end;
function TMyInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
function TMyInterfacedObject._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;
function TMyInterfacedObject._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if (Result = 0) and FDestroyed then
FreeInstance;
end;
При вызове Free для таких объектов освобождение памяти под экземпляр произойдет только в том случае, если равен нулю счетчик ссылок. Иначе - просто будет выполнен код деструктора, а освобождение памяти произойдет только после обнуления счетчика. С другой стороны, обнуление счетчика не приведет к уничтожению экземпляра до тех пор, пока явно не вызвать для данного объекта Free.