L
lich
Unregistered / Unconfirmed
GUEST, unregistred user!
熟悉C++的都知道,在C++中局部对象在离开作用域后,会自动销毁
通常不用我们一直记着去用程序释放它,
但是在Delphi中,对象通常是需要有"人"来释放它的,
通常TComponent和它的子代们都会被他们的Owner释放,
一般的对象通常也会被他们的创建者释放,
如果一旦没有释放,就会有潜在的危险,发生内存泄漏,
长时间运行的程序会慢慢吃掉服务器的大量内存,直到他们被重新启动
于是,我开始怀念C++中的对象自动释放的好处来了,
喜欢偷懒的程序员不喜欢处理"后事"的
我向一位据说是Delphi高手的大侠请教,说起这点不爽的地方
说Delphi要是也支持这种特性就好了,
高手说话了:
其实,Delphi本来就支持这种自动的对象释放特性
但是必须使用接口,接口通常有一个引用计数,
计数减小到0时,对象会自动释放自己
定义一个局部变量的接口引用变量,
在退出它的作用域后,语言的底层实现中,
会减小此接口的对象的引用计数,如果对象没有被引用了,
就会自动释放掉了
高手还给我写了个例子程序,拿出来与大家共鉴
定义一个支持接口的对象,同时实现引用计数功能
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
{**访问Form2方法的接口}
IForm2 = interface(IInterface)
{按下Ctrl + Shift + G 生成接口的 GUID}
['{F4094D7B-9034-4F4D-A1BB-4F114E749F33}']
procedure ShowForm
stdcall;
procedure HideForm
stdcall;
end;
{**能自动释放的对象定义,一个普通的窗体}
TForm2 = class(TForm, IInterface, IForm2)
private
{ Private declarations }
protected
FRefCount: Integer;
function QueryInterface(const IID: TGUID
out Obj): HResult
override
stdcall;
function _AddRef: Integer
stdcall;
function _Release: Integer
stdcall;
procedure ShowForm
stdcall;
procedure HideForm
stdcall;
public
procedure AfterConstruction
override;
procedure BeforeDestruction
override;
class function NewInstance: TObject
override;
property RefCount: Integer read FRefCount;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.AfterConstruction;
begin
InterlockedDecrement(FRefCount);
end;
procedure TForm2.BeforeDestruction;
begin
if RefCount <> 0 then
raise EInvalidPointer.Create('Invalid ptr');
end;
function TForm2._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;
function TForm2._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then
Destroy;
end;
class function TForm2.NewInstance: TObject;
begin
Result := inherited NewInstance;
TForm2(Result).FRefCount := 1;
end;
function TForm2.QueryInterface(const IID: TGUID
out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
procedure TForm2.HideForm;
begin
Hide;
end;
procedure TForm2.ShowForm;
begin
Show;
end;
end.
同时,将Unit2加入Unit1的头部的引用单元列表中(Uses)
在Button1的OnClick事件中写入代码:
var
f2: IForm2;
begin
f2 := TForm2.Create(nil) as IForm2;
f2.ShowForm;
Sleep(2000);
运行程序,按下Button1,会看到一个窗体出现,2秒钟后它消失了
这就实现了自动释放的功能
更复杂一点,在Form1中定义一个成员变量,是一个IForm2型的接口
则对象能保持到程序退出时,Form1被释放时自动释放
代码如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Unit2, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
ff2: IForm2;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
f2: IForm2;
begin
f2 := TForm2.Create(nil) as IForm2;
f2.ShowForm;
ff2 := f2;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ff2 := nil;
end;
end.
通常不用我们一直记着去用程序释放它,
但是在Delphi中,对象通常是需要有"人"来释放它的,
通常TComponent和它的子代们都会被他们的Owner释放,
一般的对象通常也会被他们的创建者释放,
如果一旦没有释放,就会有潜在的危险,发生内存泄漏,
长时间运行的程序会慢慢吃掉服务器的大量内存,直到他们被重新启动
于是,我开始怀念C++中的对象自动释放的好处来了,
喜欢偷懒的程序员不喜欢处理"后事"的
我向一位据说是Delphi高手的大侠请教,说起这点不爽的地方
说Delphi要是也支持这种特性就好了,
高手说话了:
其实,Delphi本来就支持这种自动的对象释放特性
但是必须使用接口,接口通常有一个引用计数,
计数减小到0时,对象会自动释放自己
定义一个局部变量的接口引用变量,
在退出它的作用域后,语言的底层实现中,
会减小此接口的对象的引用计数,如果对象没有被引用了,
就会自动释放掉了
高手还给我写了个例子程序,拿出来与大家共鉴
定义一个支持接口的对象,同时实现引用计数功能
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
{**访问Form2方法的接口}
IForm2 = interface(IInterface)
{按下Ctrl + Shift + G 生成接口的 GUID}
['{F4094D7B-9034-4F4D-A1BB-4F114E749F33}']
procedure ShowForm
stdcall;
procedure HideForm
stdcall;
end;
{**能自动释放的对象定义,一个普通的窗体}
TForm2 = class(TForm, IInterface, IForm2)
private
{ Private declarations }
protected
FRefCount: Integer;
function QueryInterface(const IID: TGUID
out Obj): HResult
override
stdcall;
function _AddRef: Integer
stdcall;
function _Release: Integer
stdcall;
procedure ShowForm
stdcall;
procedure HideForm
stdcall;
public
procedure AfterConstruction
override;
procedure BeforeDestruction
override;
class function NewInstance: TObject
override;
property RefCount: Integer read FRefCount;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.AfterConstruction;
begin
InterlockedDecrement(FRefCount);
end;
procedure TForm2.BeforeDestruction;
begin
if RefCount <> 0 then
raise EInvalidPointer.Create('Invalid ptr');
end;
function TForm2._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;
function TForm2._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then
Destroy;
end;
class function TForm2.NewInstance: TObject;
begin
Result := inherited NewInstance;
TForm2(Result).FRefCount := 1;
end;
function TForm2.QueryInterface(const IID: TGUID
out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
procedure TForm2.HideForm;
begin
Hide;
end;
procedure TForm2.ShowForm;
begin
Show;
end;
end.
同时,将Unit2加入Unit1的头部的引用单元列表中(Uses)
在Button1的OnClick事件中写入代码:
var
f2: IForm2;
begin
f2 := TForm2.Create(nil) as IForm2;
f2.ShowForm;
Sleep(2000);
运行程序,按下Button1,会看到一个窗体出现,2秒钟后它消失了
这就实现了自动释放的功能
更复杂一点,在Form1中定义一个成员变量,是一个IForm2型的接口
则对象能保持到程序退出时,Form1被释放时自动释放
代码如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Unit2, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
ff2: IForm2;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
f2: IForm2;
begin
f2 := TForm2.Create(nil) as IForm2;
f2.ShowForm;
ff2 := f2;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ff2 := nil;
end;
end.