本文主要是介绍成员在类中的偏移量 类成员指针,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
---
看一道笔试题(引自程序员面试宝典):写出程序输出结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include <stdio.h> class A { public: A() {m_a = 1; m_b = 2;} ~A() {} void fun() {printf("%d %d", m_a, m_b);} private: int m_a; int m_b; }; class B { public: B() {m_c = 3;} ~B() {} void fun() {printf("%d", m_c);} private: int m_c; }; void main() { A a; B *pb = (B*)(&a); pb->fun(); } |
程序的输出结果为1。
暂且不讨论该程序设计有多么糟糕,但程序主要考察关于类对象成员调用的机制,关于这方面,据说在《深入理解C++对象模型》中有详解,我没有做深入研究,只是根据看《primer》和《C++必知必会》中的一些知识说一下自己的理解。
这里主要涉及到两方面:一是对象调用成员函数时会将调用对象与函数绑定;二是对象访问成员是根据该成员距离对象的偏移量来访问的,而不是根据成员名来访问,所谓偏移量,就是告诉你一个特定的成员位置距离对象的起点有多少个字节。
上面程序,内存中实例化了一个A类对象,然后将该地址强制转换成一个B类地址,即将该对象的地址内容强制看成一个B类对象。pb为B类的指针,理所当然调用的是B类中的fun()函数(可以跟多态的情形相比较),当调用fun()函数时,调用对象与该函数进行绑定,即fun()函数中隐含的形参this指针初始化为调用对象(A类对象)的地址,假设为0xff80。然后fun()函数打印值m_c。这里要注意,对象在访问类成员时,编译器并没有存储该对象各个成员的实际地址,而是存储了其相对于当前对象首地址的偏移量,由于B类只有一个成员m_c,在编译阶段,编译器就记录了m_c对于B类对象的偏移量为0,故访问m_c时,便是访问当前对象地址this+偏移量0,注意,this在这里绑定的是A类对象的首地址,在A类中,偏移量为0的成员是m_a,故打印出m_a的值。
关于类成员偏移量的输出,可以用程序验证。
例如如下程序:将地址0强制转换为A类对象的地址,那么打印类成员m_a和m_b的地址便是他们的偏移量,如下分别输出0, 4。
1 2 | cout<<&((A*)0)->m_a<<endl; cout<<&((A*)0)->m_b<<endl; |
再如,我们可以通过输出类成员指针来验证。
1 2 | printf("%p\n",&A::m_a); printf("%p\n",&A::m_b); |
分别输出 00000000,00000004。
如程序,&A::m_a实际是一个指向int型的A类的成员指针,用m_a初始化,即相当于:
1 | int A::*ptr = &A::m_a; |
这里说一下,输出成员指针的值,最好使用printf,%p输出指针,我曾试图使用语句
1 | cout<<&A::m_a<<&A::m_b; |
结果全是1。
究其原因,应该是ostream对象没有重载类成员指针的参数,故不能直接输出类成员指针的类型,而我们知道指针类型与bool类型的转换属于标准转换的(常常用来测试指针合法性是否为空),而ostream对象可以输出bool类型,故编译器将成员指针类型转换成了bool类型,从而输出,既然这样为什么全是输出1呢?说明地址全是合法的,即偏移量全是大于0,不对呀,第一个类成员的偏移量不是0么,这里真心不明白,不过《C++必知必会》中有这样一句话:大多数编译器都将成员指针实现为一个整数,包含被指向成员的偏移量,另外加上1(加1是为了让值0可以表示一个空的数据成员指针)。这大概就是全输出1的原因了吧。
关于成员指针
成员指针只是记录一个成员的偏移量,而非地址,因为类中没有地址,选择一个类的成员只是意味着在类中偏移,只有把这个偏移和具体对象的首地址结合,才能得到实际地址。
成员指针并不指向一个具体的内存位置,它指向的是一个类的特定成员,而不是指向一个特定对象的特定成员,最直接的理解是将其理解为一个偏移量。这个偏移量适用于某一类A的任何对象,换言之,如果一个A类对象的成员a距离起点的偏移量是4,那么任何其他A类对象中,a的偏移都是4字节。
啰嗦一大堆,总结一下就是两句话:
- 类对象访问其成员时,是根据该成员在类中的偏移量来访问的。
- 类成员指针,可以理解为指向类数据成员的一个偏移量,而非地址。
(全文完)
这篇关于成员在类中的偏移量 类成员指针的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!