来自基类delphi的免费超类对象

时间:2019-02-22 12:04:57

标签: delphi

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

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;

谢谢。

2 个答案:

答案 0 :(得分:3)

Tbase.Destroy不可能释放Tsup.o

Tsup继承了o的{​​{1}},但是由于您也为新的Tbase字段赋予了相同的名称,因此无法访问继承的{{1 }}(除指针或强制转换外)。换句话说:新引入的TStrings不会替代继承的o。它只是隐藏它。

因此o的两个版本o都存在于o 中,尽管对象很容易被访问,但它们的偏移量不同。 Tsup仅“知道”自己的Tbase,这就是o 不能释放Tbase.Destroy的原因。

您将必须在TStrings中实现( override destructor Destroy,然后在此处执行。而且应该顺序良好,请致电Tsup


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

答案 1 :(得分:2)

如@Rudy所述,OOP层次结构阻止基类释放后代引入的成员。


我想问题的要点是如何将基类中声明的对象用作派生类中不同类型对象的样板。

可以进行这样的构造,其中派生的类创建其自己的内部对象并将该对象分配给基础对象。这样,基类可以处理破坏。对所有这些进行编码将有点乏味,并可能导致混乱。


相反,请使用泛型,并让派生类为基类对象定义任何类:

program TestGenerics;
{$APPTYPE CONSOLE}

uses Classes;

type
  Tbase<T:Class> = class(TObject)  // Constrained to classes
  public
    o: T;  // Used by all derived classes. 
    constructor Create;
    destructor Destroy; override;
  end;

  Tsup<T:Class> = class(Tbase<T>) //there will be lot more classes based on Tbase<T>
  public
    constructor Create;
  end;

constructor Tbase<T>.Create;
begin
  Inherited;
end;

destructor Tbase<T>.Destroy;
begin
  o.Free;
  inherited;
end;

constructor Tsup<T>.Create;
begin
  Inherited;
end;

var
  sup : Tsup<TStrings>;
begin
  sup := Tsup<TStrings>.Create;
  try
    sup.o := TStringList.Create;
    sup.o.Add('Hello');
  finally
    sup.Free;
  end;
end.