Address: http://blog.csdn.net/smstong/article/details/6604388
First, let's ask a question. In C ++, is the this pointer in the member function always the same as the address of the object that calls this function? If your answer is: Not necessarily. At least you are a veteran. You don't need to read the following content. If your answer is yes, you are strongly advised to take a look at the following content.
Non-static member functions, whether virtual or not, hide a this pointer parameter. The purpose of this parameter is to provide a base address for the function so that the function can find the member variables of the object. Then how does a non-static member function find member variables based on the this pointer? Let's look at the example.
1. No virtual table
- # Include <iostream>
- # Include <stdio. h>
- Using namespace STD;
- Class
- {
- Public:
- Int X;
- Int y;
- Public:
- Void F1 ()
- {
- This-> x = 1;
- This-> Y = 2;
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- };
- Int main (INT argc, char ** argv)
- {
- A;
- Cout <"the address of object A is:" <& A <Endl;
- Cout <"the size of object A is:" <sizeof (a) <Endl;
- Cout <"the address of a. x member is:" <& A. x <Endl;
- Cout <"the offset of A. X Member is:" <& A: x <Endl;
- A. F1 ();
- Cin> argc;
- Return 0;
- }
Then the pseudo code of function F1 is:
* (This + & A: x-1) = 1;
* (This + & A: Y-1) = 2;
Where & A: X is the offset of member x + 1, & A: Y is the offset of member y + 1, which is the basic syntax knowledge of C ++, hope you know. But these offsets correspond to the corresponding offsets. Is it the object address? The answer is no. It is the offset relative to the first member variable, which may not be different for some objects, but for objects with classes with virtual tables, there is a difference. These offsets are determined during compilation. In this example, & A: X under VC ++ 2010 has a value of 1, & A: Y, and a value of 5. For more information about the reason, see inside the C ++ object model.
Therefore, only the value of this needs to be determined for finding the member variable. The program running result is as follows:
In this example, the object address is the same as the address of this pointer. The memory figure is as follows.
2. There is a virtual table.
- # Include <iostream>
- # Include <stdio. h>
- Using namespace STD;
- Class
- {
- Public:
- Int X;
- Int y;
- Public:
- Virtual void F1 ()
- {
- This-> x = 1;
- This-> Y = 2;
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- };
- Int main (INT argc, char ** argv)
- {
- A * P = new ();
- Cout <"the address of object A is:" <p <Endl;
- Cout <"the size of object A is:" <sizeof (a) <Endl;
- Cout <"the address of a. x member is:" <& P-> x <Endl;
- Cout <"the offset of A. X Member is:" <& A: x <Endl;
- P-> F1 ();
- Cin> argc;
- Return 0;
- }
In this case, the pseudo code of function F1 is:
* (This + 4 + & A: x-1) = 1; // + 4 because there is a virtual table pointer
* (This + 4 + & A: Y-1) = 2; // + 4 because there is a virtual table pointer
The program running result is as follows:
The memory layout is as follows:
Conclusion: The value of this is the same as the object address, and the offset of the member variable does not change because of the existence of the virtual table pointer. The member functions of classes with virtual tables have different addressing methods for member variables. Add one + 4.
3. Single inheritance
- # Include <iostream>
- # Include <stdio. h>
- Using namespace STD;
- Class
- {
- Public:
- Int X;
- Int y;
- Public:
- Void F1 ()
- {
- This-> x = 1;
- This-> Y = 2;
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- };
- Class B: public
- {
- Public:
- Int Z;
- Public:
- Virtual void F2 ()
- {
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- };
- Int main (INT argc, char ** argv)
- {
- B * pb = new B ();
- Cout <"the object address is:" <STD: Hex <STD: showbase <Pb <Endl;
- Pb-> F1 ();
- Pb-> F2 ();
- Cin> argc;
- Return 0;
- }
Running result:
Memory layout:
Conclusion: The value of this pointer is determined by two factors: one is the object address, and the other is the class that defines the member function. This points to the subobject class that defines the method in the object.
4 Multi-Inheritance
First, check whether a has a virtual function or B has a virtual function.
- # Include <iostream>
- # Include <stdio. h>
- Using namespace STD;
- Class
- {
- Public:
- Int X;
- Int y;
- Public:
- Void F1 ()
- {
- This-> x = 1;
- This-> Y = 2;
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- };
- Class B
- {
- Public:
- Int Z;
- Public:
- Virtual void F2 ()
- {
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- };
- Class C: Public A, public B
- {
- Public:
- Int;
- Public:
- Virtual void F2 ()
- {
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- Void F3 ()
- {
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- };
- Int main (INT argc, char ** argv)
- {
- C * Pc = new C ();
- Cout <"object size:" <sizeof (c) <Endl;
- Cout <"the object address is:" <STD: Hex <STD: showbase <Pc <Endl;
- PC-> F1 ();
- PC-> F2 ();
- PC-> F3 ();
- Cin> argc;
- Return 0;
- }
Result:
Memory layout:
Again, if a and B both have virtual functions.
Code:
- # Include <iostream>
- # Include <stdio. h>
- Using namespace STD;
- Class
- {
- Public:
- Int X;
- Int y;
- Public:
- Virtual void F1 ()
- {
- This-> x = 1;
- This-> Y = 2;
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- };
- Class B
- {
- Public:
- Int Z;
- Public:
- Virtual void F2 ()
- {
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- };
- Class C: Public A, public B
- {
- Public:
- Int;
- Public:
- Virtual void F2 ()
- {
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- Void F3 ()
- {
- Cout <"the value of this pointer is:" <STD: Hex <STD: showbase <This <Endl;
- }
- };
- Int main (INT argc, char ** argv)
- {
- C * Pc = new C ();
- Cout <"object size:" <sizeof (c) <Endl;
- Cout <"the object address is:" <STD: Hex <STD: showbase <Pc <Endl;
- Cout <"X address" <& PC-> x <Endl;
- Cout <"Z address" <& PC-> Z <Endl;
- PC-> F1 ();
- PC-> F2 ();
- PC-> B: F2 ();
- PC-> F3 ();
- Cin> argc;
- Return 0;
- }
Result:
Memory layout:
Conclusion: The method for determining the value of this pointer is verified again. This must always point to the subobject class that defines the member function. C ++ ensures that the base class subobject exactly corresponds to the base class object, so that the member function can address the offset of the variable in the class defined by the member variable.