Dynamic and forced conversion of C ++ object layout and Polymorphism

Source: Internet
Author: User
Dynamic and forced conversion of C ++ object layout and polymorphism implementation-Linux general technology-Linux programming and kernel information. The following is a detailed description. To verify the aforementioned dynamic type conversion (dynamic_cast conversion) and forced conversion of object types. We use the previously defined C041, C042, and C082 classes for verification.

Run the following code:

C082.C041: c _ = 0x05;
PRINT_VTABLE_ITEM (c041, 0, 0)
PRINT_DETAIL (C041, (C041) c082 ))
PRINT_VTABLE_ITEM (C041) c082), 0, 0)
PRINT_VTABLE_ITEM (c082, 5, 0)
C042 * pt = dynamic_cast (& c082 );
PRINT_VTABLE_ITEM (* pt, 0, 0)

Rows 2nd and 5th print the information in the original object for convenience. Lines 3rd and 4 forcibly convert the C082 object type and print the converted object memory information and virtual table information respectively. In row 3, we used dynamic_cast to perform a dynamic type conversion from the pointer of the subclass to the pointer of the right parent class, and then printed the information of the object to which the Pointer Points.

Result:

C041: objadr: 0012FA74 vpadr: 0012FA74 vtadr: 0045B364 vtival (0): 0041DF1E
The detail of C041 is 64 b3 45 00 05
(C041) c082): objadr: 0012F2A3 vpadr: 0012F2A3 vtadr: 0045B364 vtival (0): 0041DF1E
C082: objadr: 0012FA50 vpadr: 0012FA55 vtadr: 0045B36C vtival (0): 0041D483
* Pt: objadr: 0012FA55 vpadr: 0012FA55 vtadr: 0045B36C vtival (0): 0041D483

First, we will compare the last two rows. From the objadr column, we can know that pt is not the starting address of the c082 object, instead, it points to the address of the 2nd virtual table pointers of c082 (because the value of objadr in the last row is equal to the value of vpadr In the last 2nd rows ). The vpadr value in the penultimate row is the 2nd virtual table pointer of the c082 object (we specified the offset value 5 in the output ). This address is part of the c082 object inherited from the C042 class, that is, in addition to changing the type information during dynamic type conversion, the compiler also adjusts the pointer position, to ensure the correctness of the conversion semantics. Therefore, we can know that dynamic_cast must be used to convert the type of the pointer to a class object with a complex inheritance structure (generally in the inheritance tree for up or down conversion, it correctly handles pointer position adjustment. If the conversion is illegal, it returns a NULL pointer. Remember to perform this check when using dynamic_cast. In this article, we will save these checks for the sake of simplicity. This check can be defined by a macro to facilitate removal in the release version and improve efficiency.

Then compare the output of (C041) c082) and c082, we can find that the compiler generates a new temporary object to forcibly convert the object type, because their objadr columns are different, it indicates they are not the same object. Then observe the vtadr and vtival (0) of c041, (C041), c082, and c082. The first two rows are the same, and the last two rows are different. This also shows that when the compiler processes forced conversions, a new C041 object is actually generated. Because the forced type conversion of objects is not like the dynamic type conversion of pointers, the dynamic type conversion of pointers must also ensure the polymorphism semantics, so you only need to adjust the pointer position. The forced type conversion of objects also adjusts the entry values in virtual tables, because object type conversion does not require polymorphism. The first entry in the first virtual table of c082 class stores the address of the C082: foo () function. After converting the object type, it should be adjusted to C041 :: foo () is correct. This adjustment is too complicated, so the compiler simply creates a new temporary C041 object. The last two columns of the three rows are known. I don't know if this is a behavior defined in the C ++ Standard Specification. I will update it the next day.

When the new object is added, the compiler also copies the values of the data members of the original object that belong to the parent class. Pay attention to the second line of the Code, c082.C041: c _ = 0x05;, we first rewrite the value of the data member inherited from the C041 class in the c082 object to 0x05, the original value is 0x01, which is initialized by the C041 constructor. We observe the output of the 2nd rows. As mentioned above, the printed object is not c082 but a temporary object generated by the compiler. we can note that the last field of the object is 0x05, that is, the value of the data member. So we know that in addition to the new temporary object, the compiler also copies the values of the corresponding data members in the original object.

This is a little different from my previous understanding. intuitively, I always thought that this type of conversion would not generate new objects, but it is also right to think about this method of the compiler. If no new objects are generated, it means that it dynamically changes the value of entries in the virtual table as described above. However, the new temporary object also means that calling with the following statements may produce unexpected results.

(C041) c082). somefun ();

If the somefun function changes the object state, the status of c082 will not be changed after the code above is executed. Because somefun actually changes the temporary object, the temporary object will be thrown away after execution. This is different from the intuitive understanding. It is generally considered that this call will act on the c082 object. To verify that we declare the following two classes.

Struct C010
{
C010 (): c _ (0x01 ){}
Void foo () {c _ = 0x02 ;}
Char c _;
};
Struct C013: public C010
{
C013 (): c1 _ (0x01 ){}
Void foo () {c1 _ = 0x02 ;}
Char c1 _;
};

The two classes are inherited, each having a common member function with the same name. This function is used to rewrite the corresponding member variables of the class. We make the following calls:

C013 obj;
Obj. foo ();
(C010) obj). foo ();

The first foo call changes the c1 _ value, and the last call changes the c _ value. Intuitively, it is easy to think that after the above code is executed, the values of obj. c _ and obj. c1 _ are both 0x02. However, when we expand the obj object in the local Variable Window of the debugging environment, we can find that obj. c1 _ is 0x02, but obj. c _ is 0x01. The reason is that (C010) obj) actually produces a temporary object, so the call of the last row does not apply to the obj object.

Further, if we use the singleton mode in a class, and this class has an inheritance structure, when you want to call the parent class method by performing an upward transformation on the object in a program, a compilation error occurs because the temporary object of the parent class cannot be constructed. The premise is that the constructor of the parent class should be protected by protected, rather than private. Otherwise, the subclass cannot be constructed. I have not verified this because it is silly to call this method, but this possibility is not ruled out. The correct method for calling the last line in the above example should be:

Obj. C010: foo ();

  

In this way, you can call the override function in the parent class, and it also works on the correct object.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.