Recent

Author Topic: [solved] Constructor not being called.  (Read 519 times)

mungo

  • Newbie
  • Posts: 6
[solved] Constructor not being called.
« on: January 27, 2023, 03:06:31 pm »
When this is run -
program test1;
{$mode objfpc}
type
   TA = class
      constructor create;
      function WhoAmI: string; virtual;
   end;
   TB = class(TA)
      constructor create;
      function WhoAmI: string; override;
   end;
   TC = class of TA;
constructor TA.Create;
begin
   WriteLn('constructor A and I am ', WhoAmI);
end;
function TA.WhoAmI: string;
begin
   Result:= 'TA';
end;
constructor TB.Create;
begin
   WriteLn('constructor B and I am', WhoAmI);
   inherited Create;
end;
function TB.WhoAmI: string;
begin
   Result:= 'TB';
end;
function DoCreate(aClass: TC): TA;
begin
   Result:=aClass.Create;
end;
var
   Z: TA;
begin
   Z:= DoCreate(TB);
end.
The output is -
constructor A and I am TB

Can anyone please explain why TB.constructor is not called.
Changing the last 4 lines to
var
   Z: TB;
begin
   Z:= TB(DoCreate(TB));
end.
produces the same output.
« Last Edit: January 27, 2023, 03:24:55 pm by mungo »

TRon

  • Hero Member
  • *****
  • Posts: 2435
Re: Constructor not being called.
« Reply #1 on: January 27, 2023, 03:16:07 pm »
Can anyone please explain why TB.constructor is not called.

Because:
Code: Pascal  [Select][+][-]
  1. function DoCreate(aClass: TC): TA;
  2. begin
  3.         Result:=aClass.Create;
  4. end;
  5.  
aClass is class of TA (and not TB).

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Constructor not being called.
« Reply #2 on: January 27, 2023, 03:19:07 pm »
You are calling  (class of TA).create, which will only find TA.Create, and not TB.Create.

Make TA's constructor virtual, and mark TB's contructor with "override (iow the same as the function).


mungo

  • Newbie
  • Posts: 6
Re: Constructor not being called.
« Reply #3 on: January 27, 2023, 03:23:48 pm »
Yes, that works. Thank you very much.

Thaddy

  • Hero Member
  • *****
  • Posts: 14214
  • Probably until I exterminate Putin.
Re: [solved] Constructor not being called.
« Reply #4 on: January 27, 2023, 03:38:35 pm »
The code should be like this, because it should always return TB and never TA:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. type
  3.    TA = class
  4.       constructor create;virtual;
  5.       function WhoAmI: string; virtual;
  6.    end;
  7.    
  8.    TB = class(TA)
  9.       constructor create;override;
  10.       function WhoAmI: string; override;
  11.    end;
  12.    
  13. constructor TA.Create;
  14. begin
  15.    WriteLn('constructor A and I am ', WhoAmI);
  16. end;
  17.  
  18. function TA.WhoAmI: string;
  19. begin
  20.    Result:= 'TA';
  21. end;
  22.  
  23. constructor TB.Create;
  24. begin
  25.    WriteLn('constructor B and I am ', WhoAmI);
  26.    inherited Create;
  27. end;
  28.  
  29. function TB.WhoAmI: string;
  30. begin
  31.    Result:= 'TB';
  32. end;
  33.  
  34. var
  35.    Z: TA;
  36. begin
  37.    Z:= TB.Create;  // should always return TB even if inherited.
  38.    Z.Free;
  39. end.

Maybe you mean this:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. type
  3.    TA = class
  4.       constructor create;virtual;
  5.    end;
  6.    
  7.    TB = class(TA)
  8.       constructor create;override;
  9.    end;
  10.    
  11. constructor TA.Create;
  12. begin
  13.    WriteLn('constructor A and I am ', TA.Classname);
  14. end;
  15.  
  16.  
  17. constructor TB.Create;
  18. begin
  19.    WriteLn('constructor B and I am ', TB.ClassName);
  20.    inherited Create;
  21. end;
  22.  
  23. var
  24.    Z: TA;
  25. begin
  26.    Z:= TB.Create;  // should return current, subs. ancestor.
  27.    Z.Free;
  28. end.
In this case both constructors ID themselves.

Another real-world example:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. uses classes;
  3.  
  4. var
  5.    Z: TStrings;
  6. begin
  7.    Z:= TSTringlist.Create;  
  8.    writeln(Z.Classname);
  9.    writeln(Z.ClassParent.Classname);
  10.    Z.Free;
  11. end.


« Last Edit: January 27, 2023, 03:59:39 pm by Thaddy »
Specialize a type, not a var.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5448
  • Compiler Developer
Re: [solved] Constructor not being called.
« Reply #5 on: January 27, 2023, 04:37:45 pm »
The code should be like this, because it should always return TB and never TA:

That's not what mungo asked for. marcov's solution is the correct one for that.

 

TinyPortal © 2005-2018