So TVoid would be a pointer (like any object) to the instance-mem. The instance-mem would have a pointer to the VMT, but the VMT would be 0 bytes.
Hypothetically: would a TVoid require the capability of virtual methods, or could that be added in its descendants, i.e. TObject et al.?
It could be addressed per "type" but not per "descendant", as that would create incompatible types. (And of those we have enough)
That is, as soon as a class (or subclass (aka always)) introduces the need for a vmt, it can no longer be stored in anything that does not have that space for the PVMT.
So if TVoid should be a real base class, then it needs to have a PVMT.
And the PVMT points to more than just the virtual methods (for classes, different with old style objects).
The PVmt has pointers for
- the RTTI too(for manage types, even if only in some descendant),
- the parent class type (for is operator).
- other stuff (not reviewed)
The PVMT, could have zero methods in it. But must exist.
// TMyObject > TObject > TMyVoid > TVoid
var Foo: TVoid;
begin
Foo := TMyObject.create;
if Foo is TMyVoid then ; // works only via PVmt for TVoid (ref to base class)
Foo.Free; // If TMyObject has managed types their memory will leak, unless RTTI (e.g. via PVmt) exists in TVoid.
end;
Old style objects have a different vmt, therefore this is not comparable.
And also you can not store a TMyOldChildType in a variable that is TMyOldParentType. (you can have pointers of those types work like that).
But "Dispose( PMyOldParentType(ptr) );" would leak managed types introduced in TMyOldChildType (not tested, but pretty sure)
"AfterConstruction" and "NewInstance" are virtual methods. They could be introduced by a descendent.
Though for "NewInstance" it really makes no sense at all to drop it (from declaration). What would be the gain?
- 1 pointer (2 bytes on some embedded, 4 or 8 otherwise) per class (not instance)
On embedded, how many classes will you have? Say 50, then its 100 to 200 bytes. If unlucky some of it may be eaten by new code that gets generated, as instances still need memory.
- 1 indirect call converted to direct call.
Yet the latter (indirect call) can be removed by WPO (de-virtualization). So no need to alter the type definitions. (not sure if current WPO would do it)
Technically the first (saving the pointer) could also be done by WPO. Once it is entirely de-virtualized, it could be scratched from the VMT. => Only currently that part of the VMT is hardcoded, and can not be altered. Yet making it modify-able is less a task, than any adding (even part of) TVoid.
In the same way, unused methods (access to unit name, access to class name) could be reduced (by WPO), and (again currently hardcoded, not modify-able) the RTTI could shrink. (Again not trivial, but in theory...)