是否可以从基类中释放超类中的对象?

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继承自oTbase,但是由于您也为新的TStrings字段赋予了相同的名称,因此您将无法再访问继承的o(除非具有指针或强制转换)。换句话说:新引入的o不会替代继承的o。它只是将其隐藏。

因此,o的两个版本都存在于Tsup中,在对象中的偏移量不同,尽管只有一个易于访问。 Tbase仅“知道”自己的o,这就是为什么Tbase.Destroy无法释放TStrings的原因。

您将必须在destructor Destroy中实现(覆盖)Tsup并在此处执行。而且为了保持良好状态,应调用inherited



真正的问题是新的o不能替换继承的o。它们的偏移量不同。编译代码时,生成的代码将使用它们在对象中的偏移量来访问成员字段,因此基类将始终以其固定偏移量访问其自己的,而永远不会访问任何其他字段,即使它具有相同的偏移量名称,在子孙类中。

10-05 22:16