是否可以对非虚拟构造函数或方法的层次结构执行“超级继承的构造函数”调用?

时间:2014-01-14 20:16:48

标签: delphi constructor delphi-xe5

假设在Delphi中你有这些类:

type
   TClass1 = class
     public
      constructor Create;
   end;

   TClass2 = class(TClass1)
     public
      constructor Create;
   end;

   TClass3 = class(TClass2)
     public
      constructor Create;
   end;

请注意,TClass1.Create不是虚拟的,TClass2和TClass3声明了一个非虚拟的构造函数。

假设我想从TClass3.Create中调用TClass1的Create constructor-method,但不调用TClass2.Create中的构造函数代码?这种语言是否可以在不使用RTTI的情况下使用?

我认为没有这样的语法,但我想要的是:

constructor TClass3.Create;
begin
  super inherited Create; // Invoke TClass1.Create
end;

我能得到的最接近的是编译但只是泄漏一个对象,因为它正在进行单独的TClass1.Create构造。

constructor TClass3.Create;
begin
   TClass1.Create; // returns new TClass1, discards and leaks it.
   // other initialization here.
end;

在我看来,TClass1.Create中的代码TClass3.Create调用编译,我不能称之为正确,这是错误的,因为它泄漏了一个对象。这样做的正确方法是什么?

更新请注意,大卫的答案适用于没有虚拟构造函数的类层次结构,仅限于我最初的要求。如果您有虚拟构造函数并且TClass2和TClass3覆盖它们,那么他的答案将不适用于您的代码。如果我用虚拟构造函数(或者不是构造函数的虚拟方法)问过上面的问题,那么答案就是“除了非常严重的虚方法表黑客外,你根本不能这样做”。另请注意,链接的“可能重复”不是重复的,因为当您根据情况添加/减去虚拟方法时,答案会发生变化。

2 个答案:

答案 0 :(得分:2)

跳过继承层次结构层没有语法支持。你可以做你想做的唯一方法就是这样:

TClass1(Self).Create;

一个完整的示例程序,用于演示:

type
  TClass1 = class
    constructor Create;
  end;

  TClass2 = class(TClass1)
    constructor Create;
  end;

  TClass3 = class(TClass2)
    constructor Create;
  end;

constructor TClass1.Create;
begin
  Writeln('TClass1');
end;

constructor TClass2.Create;
begin
  inherited;
  Writeln('TClass2');
end;

constructor TClass3.Create;
begin
  TClass1(Self).Create;
  Writeln('TClass3');
end;

begin
  TClass3.Create;
  Readln;
end.

<强>输出

TClass1
TClass3

答案 1 :(得分:2)

虽然你不应该这样做,但你实际上可以使用内联汇编代码实现它:

constructor TClass3.Create;
begin
  asm
    mov eax, Self
    call TClass1.Create;
  end;
  Writeln('TClass3');
end;

但请记住,这实际上与理论上的超级继承(将跳过一个继承级别)不同,而这只是调用所述方法。因此,如果您在TClass2和TClass3之间引入另一个继承级别TClass2b,它将跳过它。