C ++ basic series-pointer to data members

Source: Internet
Author: User

The pointer to a data member is a mysterious and useful language feature, especially if you need to investigate the underlying layout of class members in detail. This investigation can be used to determine whether the vptr is placed at the beginning or end of the class. Another purpose is to determine the order of access functions in the class.

Consider the following point3d declaration. There is a virtual function, a static data member, and three coordinates:

Class point3d {

Public:

Virtual ~ Point3d ();

//...

Protected:

Static point3d origin;

Float x, y, z;

}

Each point3d object contains three coordinate values: X, Y, Z, and a vptr. The origin of the static data member will be placed outside the class object. The only difference that may be caused by different compilers is the location of the vptr. The C ++ standard allows a vptr to be placed anywhere in an object: At the beginning, at the end, or between each members. However, in fact, all compilers do not place the vptr in the object's header, but at the end of the object.

 

So what does it mean to take the address of a coordinate Member? For example, what is the value of the following operation:

& Point3d: Z;

The preceding operation obtains the offset of zcoordinate in the class object ). The minimum value is the sum of the sizes of X and Y, because the C ++ language requires that the order of members in the same access level should be the same as the declared order. On a 32-bit machine, each float is 4 bytes, so we should expect that the value we just obtained is 12 (on a 32-bit machine, A vptr is 4 bytes ).

However, this expectation is still one byte smaller. For C and C ++ programmers, this is a bit of an age error. If the vptr is placed at the end of the object, the offsets of the three coordinate values in the object layout are 0, 4, and 8. If the vptr is placed at the beginning of the object, the offsets of the three coordinate values in the object layout are 4, 8, and 12, respectively. However, if you get the data members address, the returned value is always 1, that is, 1, 5, 9, 5, 9, 12, and so on.

# Include <iostream>

 

Class point3d {

Public:

Virtual ~ Point3d (){};

//...

Public: // If you change to private or protected, an error is returned.

Static point3d origin;

Float X;

Float y;

Float Z;

};

 

Int main ()

{

Printf ("& point3d: x = % P/N", & point3d: X );

Printf ("& point3d: Y = % P/N", & point3d: Y );

Printf ("& point3d: z = % P/N", & point3d: Z );

STD: cout <"& point3d: x =" <& point3d: x <STD: Endl;

STD: cout <"& point3d: Y =" <& point3d: y <STD: Endl;

STD: cout <"& point3d: z =" <& point3d: z <STD: Endl;

 

Return 0;

}

 

Output result:

& Point3d: x = 00000004

& Point3d: Y = 00000008

& Point3d: z = 0000000c

& Point3d: x = 1

& Point3d: y = 1

& Point3d: z = 1

Press any key to continue

 

In vc6.0, there is no increase of 1, probably because visual c ++ has made special processing.

In vc6.0, the data can run normally in the form of printf or cout, but the results are inconsistent. When STD: cout is used, all outputs are 1. What should I explain?

The above program cannot be compiled if the data member is private or protected, but the example in the book is protected. What is the author's test program?

(The above program in vc6.0, virsual studio2008, DEV-C ++ test, and "in-depth exploration of C ++ Object Model" p131 corresponding to the description of some differences)

Why is the returned value one byte more? This byte is used to distinguish between "no pointer to any data member" and "pointer to the first data member. Consider the following example:

Float point3d: * P1 = 0;

Float point3d: * P2 = & point3d: X;

// Point3d: * indicates the pointer type of "pointing to point3d data member ".

 

If (p1 = P2 ){

Cout <"P1 & p2 contain the same value .";

Cout <"they must address the same Member !" <Endl;

}

To distinguish P1 and P2, each real member offset value is added with 1. Therefore, whether the compiler or the user must remember to subtract 1 before using this value to indicate a member.

 

After fully understanding "pointer to data members", we should explain:

& Point3d: Z; and & origin. Z

The difference between them is very clear: Take the address of a non-static data member, it will get its offset in class, obtain the address of a data member bound to a real class object and obtain the real address of the data member in the memory. The Return Value Type of & origin. Z should be: Float * instead of: Float point3d ::*.

 

# Include <iostream>

 

Class point3d {

Public:

Virtual ~ Point3d (){};

//...

Public:

Float X;

Float y;

Float Z;

};

 

Int main ()

{

Point3d origin;

Printf ("& origin. z = % P/N", & origin. z );

 

Return 0;

}

Output result:

& Amp; origin. z = 0013ff7c

 

References:

In-depth exploration of the C ++ Object Model

Related Article

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.