7

Is it ok to initialize members field before calling inherited in create ?

IE:

constructor TMyObject.create(AOwner: TComponent);
begin
  fMyField := xxx;
  inherited
end;

instead of normal way :

constructor TMyObject.create(AOwner: TComponent);
begin
  inherited
  fMyField := xxx;
end;

just to know is their is any drawback i didn't see ...

1 Answers1

11

When an instance of a class is instantiated, the memory is allocated and default initialized (e.g. filled with zeros), and then the constructor is called. So, any code in a constructor executes after the default initialization, which would be the one timing issue that you might imagine scuppering what you are doing.

However, code such as yours is usually indicative of a deeper design malaise. How could it matter whether you initialized a value before calling the inherited constructor? There are two reasons I can imagine where you might be tempted to do this:

  1. If the field in question is declared in your derived class, then the only way the ancestor code could access it is by calling a virtual (or dynamic) method. And doing so in a constructor is dangerous because the object is only partially created. That's a big toxic code smell.

  2. If the field in question is declared in the ancestor classes, you might be using this mechanism to in effect pass an argument from derived class to ancestor. That's a rather weird way of doing it. A much more appropriate way would be to use arguments in your constructor.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 4
    This reminds me of the `TThread` flaws in Delphi5, where you in some cases needed to call the `inherited` last in the constructor. [Delphi: Should a thread ever be created “not suspended”?](https://stackoverflow.com/a/17748469/576719). – LU RD Sep 08 '17 at 10:00
  • 2
    This is the case with _Forms_ when `OldCreateOrder` is true, which calls the `OnCreate` event inside the `inherited Create`. That is why I always make sure that `OldCreateOrder` is false, because then `OnCreate` is called in `AfterConstruction` when all constructors are finished. – Uwe Raabe Sep 08 '17 at 10:36
  • 1
    @Uwe `procedure TMyBaseFormClass.ReadState(Reader: TReader); begin Reader.OnFindComponentClass := FindComponentClass; inherited; OldCreateOrder := False; end; ` ;-) – David Heffernan Sep 08 '17 at 10:37
  • i know about the design malaise, but sometime (like with tthread) you have no real other choice –  Sep 08 '17 at 11:45
  • Unless you are using Delphi 5 or earlier, then you are mistaken regarding `TThread`. Perhaps you could explain why you feel this is necessary? – David Heffernan Sep 08 '17 at 11:50