Accessing virtual methods of ancestor classesquestions raised
in a virtual method covered by subclasses, the implementation of the parent class can be called with inherited , but sometimes we do not need the implementation of the parent class, but rather we want to jump over the parent class's method of calling the ancestor class directly.
For example, suppose there are three classes that are implemented as follows:
Type
Tclassa = Class
Procedure Proc; Virtual
End
TCLASSB = Class (Tclassa)
Procedure Proc; Override
End
TCLASSC = Class (TCLASSB)
Procedure Proc; Override
End
Implementation
Procedure Tclassa.proc;
Begin
ShowMessage (' Proc of Class A ');
End
Procedure Tclassb.proc;
Begin
ShowMessage (' Proc of Class B ');
End
Procedure Tclassc.proc;
Begin
ShowMessage (' Proc of Class C ');
End
Call the virtual method Procwith the following code:
Var
C:tclassa;
Begin
C: = tclassc.create;
C.proc;
C.free;
End
We know that the final call is Tclassc.proc; If you add inheritedto the tclassc.proc , tclassb.proc can get the call But now, what if you want to call Tclassa.procdirectly in tclassc.proc ?
the way to solve
If it is C + +, just write this:tclassc::P Roc.
In Delphi But there is no way to do,Delphi does not allow us to jump-level call ancestor class method. Nonetheless, it is possible to find a solution from another perspective.
The solution is VMT, each class is a pointer to VMT , and VMT is actually used to save the virtual method. In the affirmative of the VMT , all the virtual methods from the ancestor class are listed, only the VMT of the Tclassa is shifted to Proc, and then the call can be called.
Let's see how this problem can be solved:
Procedure Tclassc.proc;
Type
Tproc = procedure of object;
Var
M:tmethod;
Begin
M.code: = Ppointer (Tclassa) ^;
M.data: = self;
Tproc (M) ();
ShowMessage (' Proc of Class C ');
End
Once the call is executed, you can see that it pops up first:Proc of Class A; then pops up:Proc of Class C. This indicates that Tclassa.proc was called in the Tclassc.proc .
tclassa Span style= "font-family: ' Times New Roman ';" >VMT 0 offset is proc addresses, and inherits from tobject , tobject itself has some virtual methods, such as afterconstruction , so where are these stored?
The secret is on the negative offset of the VMT , which declares the structure offset of the virtual table in the System unit and has the afterconstruction entry point in the negative direction. It should be noted that several of the positive orientations of the structure offsets are declared in theSystem unit, and the 0 offset (vmtqueryinterface) is not a storage QueryInterface, instead, the first virtual method (except tobject ) is stored.
Here is the VMT layout from the Help:
Offset Type Description
-76 Pointer Pointer to virtual method table (or nil)
-72 Pointer Pointer to Interface table (or nil)
-68 Pointer Pointer to Automation information table (or nil)
-64 Pointer Pointer to instance initialization table (or nil)
-60 Pointer Pointer to type information table (or nil)
-56 Pointer Pointer to field definition table (or nil)
-52 Pointer Pointer to Method definition table (or nil)
-48 Pointer Pointer to dynamic Method table (or nil)
-44 Pointer Pointer to short string containing class name
-40 Cardinal instance size in bytes
-36 Pointer Pointer to a Pointer to ancestor class (or nil)
-32 Pointer Pointer to entry point of Safecallexception method (or nil)
-28 Pointer entry point of Afterconstruction method
-24 Pointer entry point of Beforedestruction method
-20 Pointer entry point of Dispatch method
-16 Pointer entry point of DefaultHandler method
-12 Pointer entry point of Newinstance method
-8 Pointer entry point of Freeinstance method
-4 Pointer entry point of Destroy destructor
0 Pointer entry point of first user-defined virtual method
4 Pointer entry point of second user-defined virtual method
PostScript
It is not safe to call virtual methods with virtual tables, since Borland (codegear) does not assure you that each Delphi version of the VMT layout is the same.
Therefore, the use of this method should be cautious.
http://blog.csdn.net/linzhengqun/article/details/1755493
Accesses the virtual method of the ancestor class (direct access to the ancestor class's vmt, but this method may not be reliable in the new version)