Previously, when using pointers, we were often confused about the pointer type. Since all pointers only occupy 4 bytes, so what is the role of the corresponding pointer type in the pointer conversion process. Recently, I finally understood their relationship. The related descriptions are as follows:
1. Prerequisites
First, a zooanimal class is defined as follows:
Class zooanimal {public: zooanimal (); Virtual ~ Zooanimal (); Virtual void rotate (); protected: int LOC; string name ;};
2. Description
Define the following three pointers:
Zooanimal * PX; int * PI; array <string> * PTA;
From the perspective of memory requirements, there is no difference. All three of them need enough memory to place a machine address (4 bytes on 32-bit machines ). The difference between pointers of different types is that the pointer type is not different or the content is different, but the object types it addresses are different. That is to say, the "pointer type" will teach the compiler how to explain the memory and its size in a specific address:
1. An integer pointer to address 1000. on 32-bit machines, it will cover the address space of 1000--1003.
2. If the string is a traditional 8-bytes (including a 4-bytes character pointer and an integer used to represent the string length), then a zooanimal pointer will span the address space from 1000--1015. As shown in:
What kind of address space will a pointer pointing to address 1000 and its type is void? Yes, we don't know! This is why a pointer of the type void * can only contain one address and cannot be used to operate the object.
Therefore, cast is actually a compiler instruction. In most cases, it does not change the real address contained in a pointer, it only affects the Explanation of "memory size and content identified.
3. After adding Polymorphism
Now, let's define a bear as a zooanimal. Of course, this task can be completed through "Public inheritance:
Class bear: Public zooanimal {public: bear ();~ Bear (); void rotate (); Virtual void Dance (); protected: Enum dances {...}; dances dances_known; int cell_block;}; bear B ("yogi"); bear * pb = & B; bear & RB = * pb;
What kind of memory requirements does B, Pb, and Rb have? Either pointer or reference requires only one word space (4-bytes on 32-bit machines ). Bear object requires 24 bytes, that is, 16 bytes of zooanimal plus 8 bytes of bear. The following figure shows the possible memory layout:
Well, suppose our bear object is placed at address 1000. What is the difference between a bear pointer and a zooanimal pointer?
Bear B; zooanimal * PZ = & BL; bear * pb = & B;
Each of them points to the first byte of the bear object. The difference is that the addresses covered by PB include the whole Bear object, while the addresses covered by PZ only include zooanimal subobject in Bear object.
Except for members in zooanimal subobject, you cannot use PZ to directly process any bear menbers. The only exception is through the Virtual mechanism:
// Invalid: cell_back is not a member of zooanimal, although we know that PZ currently points to a bear object. Pz-> cell_back; // OK: After a clear downcast operation, there is no problem! (Bear *) PZ)-> cell_block; // The following is better, but it is a run-time operation (high cost) if (bear * master = dynamic_cast <bear *> (PZ) master-> cell_block; // OK, because cell_block is a member of bear. Pb-> cell_block;
When we write:
Pz-> rotate ();
The PZ type determines the following two points during the compilation period:
1. Fixed available interfaces. That is to say, PZ can only call the public interface of zooanimal.
2. The access level of this interface (for example, rotate () is a public member of zooanimal ).
At each execution point, the object type referred to by PZ can be used to determine the entity called by rotate (). The encapsulation of type information is not maintained in PZ, but maintained in link, this link exists between "vptr of object" and "virtual table referred to by vptr"
In addition, the polymorphism of C ++ is implemented through pointers and references, for example:
Bear B; zooanimal Za = B; // call zooanimal: Rotate () Za. Rotate ();
AboveCodeWhen a bear object is used to initialize a zooanimal object, the bear object will be cropped, but information related to zooanimal will be retained. Therefore, Za. Rotate () must call rotate () in zooanimal, so polymorphism cannot play a role in "direct access to objects.
Bibliography:
In-depth exploration of the C ++ Object Model