前言:做Delphi很多年了,打算留下了啥,所以准备写博客了。
关于对象的创建和释放,相信大家都非常熟悉了,在这里我打算浅谈一下。
本文中我将对象分为2大类,组件对象和非组件对象,暂时不考虑接口以及实现接口的类。
组件对象,也就是从TComponent继承下来的类对象。其它的就归于非组件对象。各位不要太过纠结,给我举反例。
- 非组件对象
比如Tlist、TCollection等等,此类对象必须手动释放,建议写成try-finally块
比如: try
L := TList.create;
...你的过程
Finally
L.free;
End;
- 组件对象
这是本文的重点,因为组件对象比较特殊。
我们首先关注一下组件对象的构造函数,其在VCL中的原型是:
constructor TComponent.Create(AOwner: TComponent);
begin
FComponentStyle := [csInheritable];
if AOwner <> nil then AOwner.InsertComponent(Self);
end;
请注意它有一个参数 AOwner: TComponent
其中执行了一个方法 AOwner.InsertComponent(Self);
VCL中的原型函数是:
procedure TComponent.InsertComponent(AComponent: TComponent);
begin
AComponent.ValidateContainer(Self);
ValidateRename(AComponent, '', AComponent.FName);
Insert(AComponent);
AComponent.SetReference(True);
if csDesigning in ComponentState then
AComponent.SetDesigning(True);
Notification(AComponent, opInsert);
end;
procedure TComponent.Insert(AComponent: TComponent);
begin
if FComponents = nil then FComponents := TList.Create;
FComponents.Add(AComponent);
AComponent.FOwner := Self;
end;
FComponents: TList;
这些方法全部是TComponent类的方法,也就是说所有的组件都具有这些方法。通过观察原代码可知:Create方法中,除了创建对象外,它会将当前创建的组件对象加入到AOwner的
FComponents 里面,实际上这个FComponents是一个List,我们可以称呼它为属主。说人话就是:比如btn = Tbutton.Create(Self) --Self是一个form。在这里创建了一个button,创建完毕后,btn的属主就是form,然后btn就加入到了form的FComponents属性
接下来观察一下析构函数
destructor TComponent.Destroy;
begin
Destroying;
if FFreeNotifies <> nil then
begin
while Assigned(FFreeNotifies) and (FFreeNotifies.Count > 0) do
TComponent(FFreeNotifies[FFreeNotifies.Count - 1]).Notification(Self, opRemove);
FreeAndNil(FFreeNotifies);
end;
DestroyComponents;
if FOwner <> nil then FOwner.RemoveComponent(Self);
inherited Destroy;
end;
析构函数更加详细的代码,读者可自行查阅VCL.这个析构函数的意思就是:当组件在释放时候,会做一下几件事
- 释放自己本身内部的组件,比如form和panel会释放放在里面的组件
2、释放FComponents属性里面的对象
3、如果有属主,通知属主对象,在FComponents里面移除自己
当我们知道了原理后,就可以回答一些问题了。
1、比如下列代码,有问题吗?
procedure TForm1.Button1Click(Sender: TObject);
var
btn : TButton;
begin
btn := TButton.Create(Self);
btn.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
btn : TButton;
begin
btn := TButton.Create(Self);
end;
我的回答:都是对的。其原因就是:第一个指定了属主,然后手动释放了,在释放的时候,btn就会通知form,要在FComponents里面移除自己,所以当from释放的时候,它就不会在释放btn;第二个原因就是:指定了属主,不过没有手动释放,这样在form释放自己的时候,它会去释放btn;
- 补充一下对象生命周期的问题。
对于非模态窗体,就是用show出来的窗体,因为不知道窗体什么时候需要释放,我们可以指定属主,通常是application
而模态窗体,因为它有明确的生命周期,我们知道何时该销毁它,这个时候指定不指定都可以,不过需要在窗体关闭的时候,立刻销毁它。
本文深入探讨了Delphi中组件对象的创建与释放机制,包括组件对象与非组件对象的区别,重点解析了组件对象的构造与析构过程,以及如何正确管理对象生命周期。

375

被折叠的 条评论
为什么被折叠?



