Followed by the previous article. The time was not enough and the writing was messy.
In my previous article about adding property mechanisms to C ++, I used an init_property macro to get the class pointer of the target class. I chatted with longzi longsun a few days ago, he told me a trick to get the offset address of Class Members in the class, as shown below:
(INT) (& (type_name *) null)-> member_name)
For example, I have a class.
Class
{
Public:
Virtual int show (){}
Int I1, I2;
};
Then (INT) (& (A *) null)-> I2) = 8
The offset of Class address + 8 is the address of I2 (4-byte VMT table address, 4-byte I1, so the addressing offset of I2 is 8)
I suddenly realized that I could calculate the address of the class with the attribute class in the attribute class. This is determined by the class addressing method, as shown below:
Class child
{
Public:
Int I1, I2; I1 offset is 0, I2 is 4, no VMT table
};
Class Parent
{
Public:
Int I; I offset is 0
Child * C; C offset is 4
New and delete of parnet () {...} C will not be written
};
Parent * P;
When a new parent class is required, two blocks of memory will be allocated on the heap. One is the memory occupied by the C object, and the other is the memory occupied by the P object.
The Assembly Code is as follows:
MoV ECx, P // get the pointer of P
MoV ECx, [ECx + 4] // obtain the pointer of the P object member C.
MoV eax, [ECx + 4] // obtain the address of i2.
In this way, the address is assigned to I2.
However, if the parent class is not a pointer to the Child class, but directly contains objects, the situation is different, as shown below:
Class Parent
{
Public:
Int I; I offset is 0
The child C; C offset is 4 (note that C is not a child * here)
};
Parent * P;
When a new parent class is required, only one block of memory is allocated on the heap, which occupies the memory for the p object. The C object is included in the p object and uses the P object's memory directly, i2 member (p-> C. i2), the Assembly Code is as follows:
MoV ECx, P // get the pointer of P
MoV ECx, ECx + 8 // get the address of I2 8 = C Offset + I2 offset in Class C, compilation Optimization
The address of the C object in the class P object to be addressed is as follows:
MoV ECx, P // get the pointer of P
MoV ECx, ECx + 4 // get the address P Object Pointer + offset of C
As you can see from the above, as long as you know the class C address and want to get the pointer to P, you can see the offset of the class C address in the class C object.
The process is simple. The sample code is as follows:
# Include <iostream>
Using STD: cout;
Using STD: CIN;
Using STD: Endl;
Template <typename T, typename int (* getoffset) ()>
Class Property
{
Public:
Property ()
{
Cout <"this:" <(INT) This <STD: Endl;
Cout <"Owner:" <(INT) This-getoffset () <STD: Endl;
}
};
# Define property_declare (pro_name, type_name )/
PRIVATE: int inline static pro_name ##_ offset () {return (INT) (& (type_name *) null)-> pro_name );};/
Public: Property <type_name, type_name: pro_name ##_ Offset> pro_name;
Class propertytest
{
Public:
Int I;
Public:
Property_declare (name, propertytest)
};
Int main ()
{
Propertytest * test = new propertytest ();
Cout <STD: Endl;
Cout <"Property Address:" <(INT) (& Test-> name) <STD: Endl;
Cout <"test class address:" <(INT) test <STD: Endl;
STD: cin. Get ();
Return 0;
}