3.5 指向类成员的指针知识点
来源:互联网 发布:linux ftp速度慢 编辑:程序博客网 时间:2024/06/06 20:09
<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
- 3.5 指向类成员的指针知识点
- 指向类成员的指针
- 指向类成员的指针
- 指向类成员的指针
- 指向类成员的指针
- 指向类成员的指针
- 指向类成员的指针
- 指向类成员的指针
- 指向类成员的指针
- 指向类成员的指针
- 指向类成员的指针
- 指向类成员的指针
- 指向类成员的指针并非指针
- 指向类成员的指针并非指针
- 指向类成员的指针并非指针
- 指向成员的指针
- 指向成员的指针
- 指向成员的指针
- 菜鸟学hive--UDF函数
- bailian2705
- thinkphp 中的动态表.
- 设置UIView几个角为圆角
- DialogFragment Fragment already added
- 3.5 指向类成员的指针知识点
- 在Ubuntu里安装Brackets无须下载,可以直接通过命令安装
- mac下安装cmake
- jobdu1192
- GRE写作必备句型
- thinkcentre M8400 双屏拓展设置方法
- C++ STL中Map的按Key排序和按Value排序
- 证书
- 状态模式 - 行为模式