Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to do a "super inherited constructor" invocation up a hiearchy of non-virtual constructors or methods?

Suppose in Delphi you have these classes:

type
   TClass1 = class
     public
      constructor Create;
   end;

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

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

Note that TClass1.Create is not virtual, and that TClass2 and TClass3 declare a constructor which is not virtual.

Suppose that I want to invoke TClass1's Create constructor-method, from within TClass3.Create, but not invoke the constructor-code in TClass2.Create? Is this possible within the language without recourse to RTTI?

I don't think there is such a syntax, but what I want is:

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

The closest I can get is this which compiles but just leaks an object, as it's doing a separate TClass1.Create construction.

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

It also seems to me that the code TClass1.Create invocation within TClass3.Create compiles, I cannot call it correct, it is wrong because it leaks an object. What is the correct right way to do it?

Update Note that David's answer works for a class hiearchy without virtual constructors, only, as I originally asked. His answer would not work in your code, if you had virtual constructors and TClass2 and TClass3 overrode them. If I had asked the above question with virtual constructors (or a virtual method that is not a constructor) the answer would be "you can't do it at all, except by really gross Virtual Method Table hacks". Also note that the linked "possible duplicate" is not a duplicate because the answer changes when you add/subtract virtual methods from the situation.

like image 202
Warren P Avatar asked Oct 22 '25 09:10

Warren P


2 Answers

There is no syntactical support for skipping a layer of the inheritance hierarchy. The only way you can do what you want is like this:

TClass1(Self).Create;

A complete example program to demonstrate:

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.

Output

TClass1
TClass3
like image 132
David Heffernan Avatar answered Oct 24 '25 04:10

David Heffernan


While you should not do this you actually can achieve it with inline assembly code:

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

But keep in mind that this is actually different from a theoretical super inherited (which would skip one inheritance level) while this just calls the said method. So if you introduce another inheritance level TClass2b between TClass2 and TClass3 it will skip that aswell.

like image 45
Stefan Glienke Avatar answered Oct 24 '25 05:10

Stefan Glienke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!