Is inherited keyword called automatically in Delphi? - delphi

According to this page
http://www.delphibasics.co.uk/RTL.asp?Name=Inherited
It says "It is called at the start of a constructor, and at the end of a desctructor. It is not mandatory, but recommended as good practice. "
Did I not understand correctly this? Does it mean that we don't need to put 'inherited' in constructor or destructor because it will be automatically inserted by compiler?

No, inherited isn't called automatically; you have to do it yourself (if you want to call the inherited procedure, which you normally do). And you can even choose when to do it, see, e.g., this answer. Typically you do it at the beginning of a constructor, and at the end of a destructor.

No, that's not what it means; what it's saying is that you can choose not to call it if you have a reason not to call it. You should almost always call inherited in every method you're overriding, unless you need for something not to happen in your descendant that the parent does.
Unless you have a very good reason not to do so, you should always call inherited as the first line of your constructor, and the last line of your destructor. It is never called automatically.
Delphi makes it very easy; if your overridden method has the same parameters as the parents, you don't even have to pass them on:
constructor TMyClass.Create(AOwner: TComponent);
begin
inherited; // Automatically passes AOwner to parent constructor
// Do other construction here
end;
destructor TMyClass.Destroy;
begin
// Do your own cleanup
inherited;
end;

Related

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

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 ...
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:
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.
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.

How to call functions, which require the control `Parent` to be set, in constructor?

I have a TCustomControl and I must call in the constructor some functions which require that the control has the Parent property set. I tried to set it first and it's working if I create the instance of the control at run time but when I want to put it on the form at design time I get access violation. How can I fix this ?
constructor TPathHolder.Create(AOwner: TComponent);
begin
inherited;
Parent:=TWinControl(AOwner);
//.....that function here....
end;
Do not assign Parent of control in your constructor (or in any part inside your control code). Setting parent inside control itself interferes with the way VCL framework works in both design and run-time.
Instead you can override SetParent method, and do your initialization there.
procedure SetParent(AParent: TWinControl); override;
procedure TMyControl.SetParent(AParent: TWinControl);
begin
inherited;
// put custom initialization code here
end;
Just keep in mind that this method can be called multiple times during control lifetime, and passed AParent can be nil.
You should not set the Parent in the constructor. It is as simple as that. The Parent should be set after the constructor has returned.
You will need to call these other functions, those that require Parent to be set, later. Or find a way to get the work done without requiring Parent to be set.

Delphi destructors: executing code after inherited call?

is it really okay in Delphi to execute code after the inherited call in a destructor?
You can find this in System.Classes:
destructor TThread.Destroy;
begin
[...]
inherited Destroy;
FFatalException.Free;
end;
I think, that accessing an instance member after calling the inherited Destroy method is a bad idea.
It is perfectly safe to execute code after a call to an inherited destructor, so long as that code does not rely on something that has been destroyed by that inherited destructor. In the same way it is safe to execute code before a call to an inherited constructor, so long as the code does not rely on anything instantiated in that inherited constructor.
But it is certainly true that this is not good style. There are on occasions reasons that would lead you to such code, but usually such reasons should be taken as indication that something is wrong in your design.
In the example that you give there is simply no need to write the code that way. The call to FFatalException.Free could perfectly well happen before the call to the inherited destructor.
The instance is not removed from memory by the destructor method itself but by the call of TObject.FreeInstance
TObject.FreeInstance is called, because a destructor is called, after processing the destructor code.
BTW: It is the same to the constructor. The instance is created by class function TObject.NewInstance : TObject and it is called before the constructor is called (just because it is a constructor)
Because of this, you will have a valid instance inside the whole constructor or destructor code.

What's the damage from calling inherited incorrectly?

In searching for a highly intermittent memory corruption in a Delphi XE program, I have found a class constructor which initializes a few fields in the class, and then calls inherited. I believe the initializations were added after the constructor was first written, and accidentally in the wrong place. I have now corrected it to call inherited first. The exceptions from the memory corruption almost always occur in a method of this class.
Question: is it possible that this mistake caused an intermittent memory corruption? In tracing the code, it seems not, but I would really like this fix to be what solves the intermittent issue. That it does not occur for a while after fixing the problem will not prove that it has gone away.
Some code:
Tmyclass = class
ctype : integer;
ts : tstringlist;
th : thandle;
public
Constructor Create;
Destructor Destroy; override;
...
end;
Constructor Tmyclass.Create;
begin
ctype := 3;
doinit;
inherited;
end;
Here are typical steps of an object creation:
Memory allocation of the object instance;
Fill all memory with zero (to initialize all fields, especially string);
Call all nested constructors, beginning with the latest child, letting inherited call every parent - that is why you shall write inherited in both constructors and destructors.
So, inherited calls the parent method - you can even specify a parent level, or call none if you are sure you can do that (but may break the SOLID principles).
In fact, when a constructor is called, there is an hidden parameter added to the method:
Constructors and destructors use the same calling conventions as other
methods, except that an additional Boolean flag parameter is passed to
indicate the context of the constructor or destructor call.
A value of False in the flag parameter of a constructor call indicates
that the constructor was invoked through an instance object or using
the inherited keyword. In this case, the constructor behaves like an
ordinary method. A value of True in the flag parameter of a
constructor call indicates that the constructor was invoked through a
class reference. In this case, the constructor creates an instance of
the class given by Self, and returns a reference to the newly created
object in EAX.
A value of False in the flag parameter of a destructor call indicates
that the destructor was invoked using the inherited keyword. In this
case, the destructor behaves like an ordinary method. A value of True
in the flag parameter of a destructor call indicates that the
destructor was invoked through an instance object. In this case, the
destructor deallocates the instance given by Self just before
returning.
The flag parameter behaves as if it were declared before all other
parameters. Under the register convention, it is passed in the DL
register. Under the pascal convention, it is pushed before all other
parameters. Under the cdecl, stdcall, and safecall conventions, it is
pushed just before the Self parameter.
Source: official Delphi documentation
So you can be sure that, wherever the inherited is called, it will be safely handled. For instance, initialization of fields (reset to 0) will be processed only once, before all constructors are called.
The TObject.Create default constructor (the one called in your inherited line) is just a begin end void block, which does nothing. It is not even necessary/mandatory to call inherited here, but it is a good habit, since if you change your object hierarchy, it may be needed afterall.
Only issue may be if some fields are set inside this inherited method (ctype := 2 e.g.), after having been set in the child - but this is not compiler's fault, this is up to user code!
Initializing some fields before calling the inherited constructor is not necessarily a bug. Sometimes the inherited constructor calls some virtual methods which have been overridden by the descendant and these new implementations rely on those fields to be correctly initialized.
(I am not saying that this is good design, but it's not a bug.)
In Delphi you can initialize object fields before calling inherited constructor (it does not worked in Turbo Pascal or 'old' object model, but it is allowed in Delphi 'new' object model).

Using inherited in the "Create" constructor of an TObject

Rant: Should I call "inherited" in the constructor of a class derived from TObject or TPersistent?
constructor TMyObject.Create;
begin
inherited Create; // Delphi doc: Do not create instances of TPersistent. Use TPersistent as a base class when declaring objects that are not components, but that need to be saved to a stream or have their properties assigned to other objects.
VectorNames := TStringList.Create;
Clear;
end;
Yes. It does nothing, true, but it's harmless. I think there is value in being consistent about always calling the inherited constructor, without checking to see if there is, in fact, an implementation. Some will say that it's worth calling inherited Create because Embarcadero might add an implementation for TObject.Create in the future, but I doubt this is true; it would break existing code which does not call inherited Create. Still, I think it is a good idea to call it for the reason of consistency alone.
I always do this.
If you are refactoring and move code to a common ancestor, calling the inherited Create has the following advantages:
If the common ancestor has a constructor, you can't forget to call it.
If the common ancestor has a constructor with different parameters, the compiler warns you for this.
You can also override "procedure AfterConstruction". This procedure is always called, no matter what kind of constructor.
public
procedure AfterConstruction; override;
end;
procedure TfrmListBase.AfterConstruction;
begin
inherited;
//your stuff, always initialized, no matter what kind of constructor!
end;
For example: if you want to create an object with a different constructor than the normal TObject.Create, such as TComponent.Create(AOwner) or a custom (overloaded) constructor, you can get problems because your override is not called and (in this case) your "VectorNames" variable will be nil.
I call it, except when i need a very optimized constructor.

Resources