3.5 指向类成员的指针知识点

<1> 指向类成员的指针给出的是该类成员在类中的偏移量,而不是真正的地址。即假设:

Eg:

class A
        {
            public:

                int val;
        };

    //此时有:

        &A::val;     //得到的是类成员 val 在类中的偏移量,若 vptr 在对象尾部,则该值为1(或0)

        A x;

        &x.val;  //得到的是 x 对象中类成员 val 在内存中的真正地址

<2> 指向类成员指针的值为什么总是多1的原因

Eg:

    class A
        {
            public:
                virtual ~A(){}
                int x;
                int y;
                int z;
        };

在32位的计算机上,int 所占大小是4字节,假设虚函数表的指针 vptr 放在类对象的尾部,则:

• x,y,z 的类成员的偏移分别为 0 ,4 ,8 ,但若取数据成员的地址,即看到:

• &A::x = 0x1, &A::y = 0x5, &A::z = 0x9,而不是先前所说的指向成员指针的值即为其在类对象中的偏移值

原因:为了区分一个“没有指向任何数据成员的指针”与一个“指向第一个数据成员的指针”,如下:

Eg:

            int A:: * p0 = 0;
            int A:: * p1 = &A::x;

例中,p0是没有指向任何数据成员的指针,而 p1是指向 A 的 x 成员的指针,若不将类成员指针的值设为偏移值加1,则下列判断将成立:

    if(p0 == p1);  //该判断语句将为真,而事实上 p0 与 p1 的含义并不相同

因此,将强行使类成员的指针值为偏移值加1,用以区分“没有指向任何成员的指针”与“指向第一个数据成员”的指针

<3>查看类成员指针的值
• 对于上述 class A 的例子,使用如下语句查看其指向成员的指针值(确定其偏移):

            printf("&A::x : %p\n",&A::x);           //vs 与 g++ 均输出 0x4
            printf("&A::y : %p\n",&A::y);          //vs 与 g++ 均输出 0x8
            printf("&A::z : %p\n",&A::z);         //vs 与 g++ 均输出 0xc

偏移为 4,8,12 说明虚函数表指针 vptr 放在对象的头部,且编译器进行了内部优化操作,将偏移值多增的1减了回去

• 使用 cout 将不能正确查看到偏移值,输出值均1,原因如下:!!!!!!

            cout << "&A::x : " << &A::x << endl;             //vs 与 g++ 均输出1
            cout << "&A::y : " << &A::y << endl;            //vs 与 g++ 均输出1
            cout << "&A::z : " << &A::z << endl;           //vs 与 g++ 均输出1

原因:在C++中,ostream 对象并没有重载参数为类成员指针的operator<<函数,是不能直接输出类成员指针类型,然而指针类型与bool类型的转换属于标准转换,且未声明为 explicit,而ostream 对象则重载了参数为 bool类型的输出操作符函数,因此,在这种情况下,编译器将指针值隐式转换为了 bool 类型并调用了重载输出操作符函数,同时,又因为偏移量不会为0的原因,所以输出的 bool 值全为1

• 若一定要使用cout 输出类成员指针值,则使用类型转换,如下:

    cout << "&A::x : " << &(reinterpret_cast<A*>(0)->x) << endl;             //vs 与 g++ 均输出0x4
    cout << "&A::y : " << &(reinterpret_cast<A*>(0)->y) << endl;            //vs 与 g++ 均输出0x8
    cout << "&A::z : " << &(reinterpret_cast<A*>(0)->z) << endl;           //vs 与 g++ 均输出0xc

此转换法参考自博客:http://www.ahathinking.com/archives/98.html

你可能感兴趣的:(指针,偏移量)