We know that the virtual function of C is implemented by providing a virtual function for each class. What is its memory state?
First we implement two classes with virtual functions: Classa and Classb, where classb is the derived class of ClassA, and the specific implementation is as follows:
// Classa
#include
#include
Class Classa
{
PUBLIC:
Classa ()
{
X = 0;
y = 0;
}
Virtual Void Func1 (Void)
{
Printf ("this is classa :: func1 () / n");
Return;
}
Virtual Void Func2 (Void)
{
Printf ("this is classa :: fun2 () / n");
Return;
}
INT X;
Int Y;
}
// Classb
#include
#include
Class Classb: Public Classa
{
PUBLIC:
Virtual Void Func2 (Void)
{
Printf ("this is classb :: func2 () / n");
Return;
}
Virtual Void Func3 (Void)
{
Printf ("this is classb :: func3 () / n");
Return;
}
}
It is easy to see that members of ClassA include
Virtual function: Classa :: func1 (); classa :: func2 ();
Member variable: int x; int y;
Classb members include
Virtual function: Classb :: func2 (); classb :: func3 ();
Member variable: int x; int y; (inherited by ClassA)
Moreover, ClassB overloads the second virtual function of Classa, which implements a virtual function FUNC3 ().
Therefore, we know that the memory structure of the ClassA object can be said:
& Classa :: func1 ()
& Colassa :: func2 ()
Classa ::
FUNC1 ()
{...}
Classa:
VTable
X
Y
Classa ::
FUNC2 ()
{...}
The structure of the Classb object is similar, but pay attention to classb :: func2 () is inheriting Classa.
Let's take vtbale to get the VTBALE.
First declare a ClassA object in the program
Classa CAA; // In fact we can get the address of CAA
INT * PINTA = NULL;
INT * PCAA = (INT *) (& CAA); // Pointer to object CAA
INT * const & pvtable = (int *) (*) (* pcaa); // Declare a lead pointing to the INT type pointer
// Use, and use the top 4 words of the CAA object
/// The content is initialized;
Void * pvoid;
Void (* pfun1) (void);
Void (* pfun2) (void);
Void (* pfun3) (void);
Ok, we know that the four bytes of the object CAA memory space is stored in the virtual letter of the ClassA class.
The pointer of the table, and we have gotten it, it is PVTable.
You can verify it with the following statement:
PINTA = (int *) (& CAA);
Printf ("The Memory Content of Class Caa: / N");
Printf ("/ t vTable:% x / n", * (PINTA));
Printf ("/ t x:% d / n", * (PINTA 1));
Printf ("/ t y:% d / n", * (PINTA 2));
Well, the results of operation are as follows:
The Memory Content of Class CAA:
VTable: 415394
x: 0
Y: 0
After successful VTABLE, our work is to get through vTable
The virtual function table.
This is already very simple:
PVOID = (int *) (* pvtable);
PFUN1 = (void (*) (void)) PVOID; // This is to point to the first virtual function function
// The pointer of the code segment is
PVOID = (int *) (* (pvtable 1));
PFUN2 = (VOID) (*) (void)) PVOID; // This is to point to the second virtual function function
// The pointer of the code segment is
Then we execute the two pointers to perform the function to verify that we have achieved it.
The pointer of the virtual function.
PFUN1 ();
PFUN2 ();
You can get the output:
This is classa :: func1 ()
This is classa :: func2 ()
Of course, we can also print out the address of these virtual functions, so you can and Classb's vTable
Compared (J).
The same reason can get Classb's virtual function table if we print ClassA and Classb
If the function address of each virtual function, it is easy to find the first pointer of the ClassB VTable -
Point the code segment of the first virtual function of Classb, is the first pointer to the Classa's VTable
Rong is the same. Haha, because ClassB is inherited Classa, and we don't have in classb.
Overload function Virtual Classa: FINC1 (); in fact they point to the same function body.
Note: The runtime environment of the program Intel 80x86 / WinXP / Visual C 6.0, in the program, we use
INT * PINT; VOID (*) (void); void * pvoid; int; other pointers and types
Frequent conversion, because in our environment
SizeOf (int) == sizeof (int *) = sizeof (void (*)) == 4;
That is, these types take up to 4 bytes of memory units, so the conversion between them is not drawn.
Using memory leaks, etc., just as we really do, huh, huh!
Second, we used the pointer reference
INT * const & pvtable = (int *) (* PCAA);
Not easy to use
INT * PINT; what about the same content?
This is mainly because we have to use it later.
PVOID = (int *) (* (pvtable 1));
To get the pivot of the i virtual function, if a simple application
PVOID = (int *) (* (Pint 1));
If you don't meet the target, is it different?
Yes, it is because the pointer variable Pint itself has no relationship with VTABLE in memory.
(Of course, how much is a little arbitrary J, because after all, both are in the hunter of the main function,
Although the contents in Pint and VTABLE are the same, Pint returns will be the next location of PINT in the memory in memory, which is not a pointer to the next virtual function. What is (* PINT) get something
? Don't think that it is pointed to the second virtual function. This statement does not save by PINT.
The code address of the first virtual function is self-added. In this way, we will not only get the second virtual
The address of the function, even the address of the first virtual function is destroyed! !
once again,
INT * const & pvtable = (int *) (* PCAA);
Why do you want to modify with const? Note that we have obtained (* PCAA) is no longer a variable,
But a right value, in C , allowing a reference to define a constant, the process is first using constant construction
Temporary variables (the life cycle of this temporary variable is consistent with the reference variable to be defined), and then use this temporary change
Quantity to initialize our defined reference variables, premise must use const modifications, so it will prevent it
The temporary variable is modified by the user, and this is usually not suitable.