求助:Free不调用Destroy,为什么? ( 积分: 50 )

  • 主题发起人 主题发起人 不懂大师
  • 开始时间 开始时间

不懂大师

Unregistered / Unconfirmed
GUEST, unregistred user!
TBBB = class
private
...
protected
...
procedure ClearChain;virtual
abstract;
public
...
destructor Destroy;
end;

TAAA = class(TBBB)
private
...
protected
...
procedure ClearChain;
public
...
destructor Destroy;
end;

procedure TAAA.ClearChain;
begin
...
end;

destructor TAAA.Destroy;
begin
ClearChain;
inherited;
end;

=============================================
调用代码:
var
s:TAAA;
begin
s :=TAAA.Create ;
s.Free
//用Free,TAAA.ClearChain不会执行到
// s.Destroy
//用Destroy,TAAA.ClearChain到是会执行

为什么?
 
TBBB = class
private
...
protected
...
procedure ClearChain;virtual
abstract;
public
...
destructor Destroy;
end;

TAAA = class(TBBB)
private
...
protected
...
procedure ClearChain;
public
...
destructor Destroy;
end;

procedure TAAA.ClearChain;
begin
...
end;

destructor TAAA.Destroy;
begin
ClearChain;
inherited;
end;

=============================================
调用代码:
var
s:TAAA;
begin
s :=TAAA.Create ;
s.Free
//用Free,TAAA.ClearChain不会执行到
// s.Destroy
//用Destroy,TAAA.ClearChain到是会执行

为什么?
 
class TAAA .....
public
destructor Destroy
override
// 在此调用ClearChain
...
end;

你没有加override,所以父类同名方法Destroy被覆盖了(作废)!!
 
不对啊,
TBBB = class
TAAA = class(TBBB)
如果
destructor Destroy;override;
编译错误:
[Error] Unit_PLD.pas(98): Cannot override a static method
 
如果这样调用代码:
var
s:TAAA;
begin
s :=TAAA.Create ;
s.Free ;
s.Destroy ;//这里也会非法内存访问,反之先调用Destroy也一样,Free难道不是先检测是否有Destroy,有则调用的吗?为什么我的代码用Free却不会去调用Destroy过程?帮忙看看是哪里写漏了?
 
netfool说得对,TAAA和TBBB的Destroy都要override.
不仅如此,所有的类的Destroy都要override,否则会出现意想不到的错误.
 
第一:定义析构的时候要加关键字destructor Destroy;override;
第二:在析构内部调用父类的析构应该是:inherited Destroy;
 
记得D高手突破上讲得很明确!
 
Free不调用Destroy,为什么?
因为你没有override父类的destructor Destroy,所以你使用Free的时候,编译器坚持用父类的Destroy虚拟析构方法,所以你的
destructor TAAA.Destroy;
begin
ClearChain;
inherited;
end;
没有机会被执行,当调用Free函数时
 
更有意思的是,你不override父类的destructor Destroy 虚拟方法,,Delphi会产生一警告,并且你直接调用下面的代码:
s :=TAAA.Create ;
s.Destroy

DELPHI编译器会固执的调用TOBJECT的Destroy 方法,而不是你自己TAAA的Destroy ,因为DELPHI编译器做了最后的保护!所以你的
destructor TAAA.Destroy;
begin
ClearChain;
inherited;
end;
仍然不能被执行到!

===
关于:
s.Free ;
s.Destroy ;//这里也会非法内存访问,反之先调用Destroy也一样,Free难道不是先检测是否有Destroy,有则调用的吗?为什么我的代码用Free却不会去调用Destroy过程?帮忙看
看是哪里写漏了?
因为s.Free调用的是父类的Destroy ,s.Destroy 也是调用的父类的Destroy ,两个释放的是同一块内存,所以第二次释放时就会有非法内存访问的错误了!

我也是看inside VCL才知道的,不明白的看一下 VCL对象的释放服务 这一节!
btw:个人感觉老李好罗嗦,总是绕圈子,看的烦死了


====
type
TBBB = class
private

protected
procedure ClearChain;virtual
abstract;
public

destructor Destroy;override;
end;

TAAA = class(TBBB)
private

protected

procedure ClearChain;override;
public

destructor Destroy;override;
end;
implementation
procedure TAAA.ClearChain;
begin
end;

destructor TAAA.Destroy;
begin
ClearChain;
inherited Destroy;
end;
destructor TBBB.Destroy;
begin
inherited Destroy;
end;
 
所有的析构函数最好都要加override关键词名字也最好使用Destroy,且Destroy函数里最好有Inherited;否则都会有机会引起资源不会被释放。可以看看Free方法的源程序。里面有调用析构函数Destroy。如果方法名不为Destroy就会调用到父类的Destroy函数,可想而之。在本层的一些释放工作都不能进行。如果没有加override关键字,则会引起上层释放不干净的问题
 
如果懂了上面我所说的意思,相信你以后这个问题不会再出错了。示例上面各位都列举了。我就不多此一举了
 
哦,结贴也要留言啊?ok,谢谢,打了n多字的多点分 :)
 
嗯?哦,知道了 -_-;
 
早知道,我贴几篇小说放这里了,不用回答问题了。
 
老兄不必这么小气吧?基本上是均分了,liuxiangsoft回答的不够及题,而WoDing的代码+说明很清楚,特别是代码拷贝一下就可以看到效果,这样给分应该还算公平吧?
 
后退
顶部