是否可以从基类中释放超类中的对象?
interface
type
Tbase = class(TObject)
public
o: TObject;
constructor Create;
destructor Destroy; override;
end;
Tsup = class(Tbase)//there will be lot more classes based on Tbase
public
o: TStrings;
constructor Create;
end;
implementation
procedure main();
var
a: Tsup;
begin
a := Tsup.Create;
//
a.Free;
end;
constructor Tbase.Create;
begin
inherited;
end;
destructor Tbase.Destroy;
begin
if o <> nil then
o.Free;
inherited;
end;
constructor Tsup.Create;
begin
inherited;
o := TStringList.Create;
end;
destructor Tsup.Destroy;
begin
// let tbase to free o ?
inherited;
end;
对象o将不会在tbase类中使用(释放除外)
tsup类var o类型与tbase cass var o类型不同
是否可以在tbase.Destroy()中释放tsup.o? (所以我可以使实现析构函数Tsup.Destroy无效)
谢谢。
最佳答案
没有。Tbase.Destroy
不可能释放Tsup.o
。Tsup
继承自o
的Tbase
,但是由于您也为新的TStrings
字段赋予了相同的名称,因此您将无法再访问继承的o
(除非具有指针或强制转换)。换句话说:新引入的o
不会替代继承的o
。它只是将其隐藏。
因此,o
的两个版本都存在于Tsup
中,在对象中的偏移量不同,尽管只有一个易于访问。 Tbase
仅“知道”自己的o
,这就是为什么Tbase.Destroy
无法释放TStrings
的原因。
您将必须在destructor Destroy
中实现(覆盖)Tsup
并在此处执行。而且为了保持良好状态,应调用inherited
。
真正的问题是新的o
不能替换继承的o
。它们的偏移量不同。编译代码时,生成的代码将使用它们在对象中的偏移量来访问成员字段,因此基类将始终以其固定偏移量访问其自己的,而永远不会访问任何其他字段,即使它具有相同的偏移量名称,在子孙类中。