gpt4 book ai didi

delphi - 没有引用计数的接口(interface)

转载 作者:行者123 更新时间:2023-12-03 14:57:51 24 4
gpt4 key购买 nike

在阅读了 StackOverflow 上许多关于对接口(interface)使用自动引用计数的缺点的文章后,我开始尝试手动对每个接口(interface)实例化进行引用计数。

尝试了一整个下午后我放弃了!

为什么当我调用 FreeAndNil(p) 时会出现访问冲突?

下面是我的简单单元的完整列表。

unit fMainForm;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm4 = class(TForm)
btn1: TButton;
procedure FormCreate(Sender: TObject);
procedure btn1Click(Sender: TObject);
end;

type
IPersona = interface(IInterface)
['{44483AA7-2A22-41E6-BA98-F3380184ACD7}']
function GetNome: string;
procedure SetNome(const Value: string);
property Nome: string read GetNome write SetNome;
end;

type
TPersona = class(TObject, IPersona)
strict private
FNome: string;
function GetNome: string;
procedure SetNome(const Value: string);
protected
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
public
constructor Create(const ANome: string);
destructor Destroy; override;
end;

var
Form4: TForm4;

implementation

{$R *.dfm}

procedure TForm4.FormCreate(Sender: TObject);
begin
ReportMemoryLeaksOnShutdown := True;
end;

procedure TForm4.btn1Click(Sender: TObject);
var
p: IPersona;
begin
p := TPersona.Create('Fabio');
try
ShowMessage(p.Nome);
finally
FreeAndNil(p);
end;
end;

constructor TPersona.Create(const ANome: string);
begin
inherited Create;
FNome := ANome;
end;

destructor TPersona.Destroy;
begin
inherited Destroy;
end;

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

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

function TPersona.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := S_OK
else
Result := E_NOINTERFACE;
end;

function TPersona.GetNome: string;
begin
Result := FNome;
end;

procedure TPersona.SetNome(const Value: string);
begin
FNome := Value;
end;

end.

最佳答案

发生访问冲突是因为 FreeAndNil 接收到一个无类型的 var 参数,该参数预计是一个对象引用。您传递的接口(interface)引用不符合要求。不幸的是你只能在运行时发现。在我看来,这是反对使用 FreeAndNil 的最强点。

您的引用计数禁用了接口(interface)引用计数机制的生命周期管理。为了销毁一个对象,您需要调用它的析构函数。为了做到这一点,您必须有权访问析构函数。您的接口(interface)不会公开析构函数(也不应该)。因此,我们可以推断,为了销毁该对象,您需要有一个对象引用。

以下是一些选项:

var
obj: TPersona;
intf: IPersona;
....
obj := TPersona.Create('Fabio');
try
intf := obj;
//do stuff with intf
finally
obj.Free;
// or FreeAndNil(obj) if you prefer
end;

或者你也可以这样做

var
intf: IPersona;
....
intf := TPersona.Create('Fabio');
try
//do stuff with intf
finally
(intf as TObject).Free;
end;

关于delphi - 没有引用计数的接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13135332/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com