The lesson in this for me was that constructors must be virtual for derived class to be able to override them.
At least for now - havent investigated the reintroduce yet.
You misunderstood.
The language feature (virtual/override) is useless for constructors, because the type is known at design time already.
Override is a special language feature, that is not obvious from its name. The very feature of override is, that the type of the variable is checked at
runtime and the according method will be chosen. I.e. even if you call a method in the type of the base class, the method of the actual child class will be called. In opposite to that if you just "reintroduce" a method in the derived class, the method is called according the type of the variable and not the instance, so the method is known at
design time. "reintroduce" is a keyword, but it's optional.
I think an example is neccessary here. For procedure Foo the virtual/override-feature is used, for the procedure Bar reintroduction is used.
Type TFancy= class
Procedure Foo; virtual; //*1
Procedure Bar; //*A
end;
Type TDerivedFancy= class(TFancy)
Procedure Foo; override; //*2 (overriding the method of the base class)
Procedure Bar; //*B (reintroducing the method of the base class)
end;
var
Fancy: TFancy;
DerivedFancy: TDerivedFancy;
IMPLEMENTATION
begin
Fancy:= TFancy.Create;
DerivedFancy:= TDerivedFancy.Create;
Fancy.Foo; //Calls *1 (of course)
DerivedFancy.Foo; // Calls *2 (of course)
TFancy(DerivedFancy.Foo).Foo; //Calls *2 (!), because although via the typecast TFancy *1 should be called, it is determined on runtime, that its an the instance calling Foo is of type TDerivedFancy.
Fancy.Bar //Calls *A (of course)
DerivedFancy.Bar; //Calls *B (of course)
TFancy(DerivedFancy).Bar; //Calls *A (!), because of the typecast TFancy.
end;
The reintroduce mechanism is the "cheap" one, the compiler checks what type is the variable and the according method will be called, even if there is a derived type instance in the variable. The override mechanism needs a runtime check, i.e. extra computation time and memory, to see which instance, of base or derived type is in the variable.
For a constructor I can't see a situation, where you don't know at design time which type the constructor has, as you have to actually define the type when you call the constructor. Thus you use the
reintroduce mechanism and not
override.