class Point3d{
public:
virtual ~Point3d();
//....
protected:
static Pointed origin ;
float x,y,z ;
};
每一个Point3d class object 含有三个坐标值,依序为x、y、z,以及一个vptr。至于satic data member origin,则将放在class object之外。唯一不能确定的就是vptr的位置,根据不同的编译器厂商,可能放在最起始处、尾端或者各个member之间(但是,编译器厂商不是把vptr放在object的头,就是object的尾端)。
那么,取某个坐标成员的地址,代表什么意思?
&Point3d::z
上述的操作得到的z坐标在class object中的偏移值(offset),最低限度其值将是x,y大小的总和,*因为C++ 语言要求同一个access level中的members的排列应该与其声明顺序相同。*
如果vptr放在对象的尾端,三个坐标值在对象布局中的offset分别是0,4,8。如果vptr放在对象的起始处,三个坐标值在对象布局中的offset分别是4,8,12.然而你若去取data members的地址,传回的值总是多1,也就是1,5,9或者5,9,13等等。
使用cout不能输出
printf("&Point3d::x=%p\n",&Point3d::x);
printf("&Point3d::x=%p\n",&Point3d::x);
printf("&Point3d::x=%p\n",&Point3d::x);
为什么传回的值总是多1呢??
原因就是为了让区分一个“没有指向任何data member “的指针,和一个指向”第一个data member”的指针。
float Point3d::*p = 0 ;
float Point3d::*p1 = &Point3d::x ;
为了区分p与p1,每一个真正的member offset值都被加上1.在真正使用该值以指出一个member之前,请先减掉1。
取一个nonstatic data member 的地址将会得到 它在class 中的offset ,取一个绑定真正class object 身上的data member的地址,将会得到该member 在内存中真正的地址。把
&origin.z //float *
所得结果结果减 z的偏移值(相对于origin起始值),再加1,就得到了origin起始地址。
float Point3d::*ax = &Point3d::x ;
origin.*ax == origin.x;