看到深度探索C++对象模型3.2节,其中给出了一个判断access section出现先后顺序的模板函数如下:
template<class class_type,class data_type1,class data_type2>
char* access_order( data_type1 class_type::* mem1,data_type2 class_type::* mem2){
assert(mem1 != mem2);
return mem1 < mem2 ? "member1 first" : " member2 first";
}
用以下程序测试
class Point3d{
public:
float x;
static list<Point3d*> *freeList;
public:
float y;
static const int chunkSize = 250;
public:
float z;
};
int main(){
access_order( &Point3d::z,&Point3d::y);
return 0;
}
得到的是: '<' : illegal, right operand has type 'float Point3d::* '也就是说这里类成员指针的用法不合法。至于为什么会这样,我推测可能是“ < ”没有以 类成员指针为参数的操作符重载。
类似的问题也发生在ostream上面。例如以刚才定义的Point3d类为基础,做一下测试
int main(){
cout<< &Point3d::x<<","<<&Point3d::y
<<","<< &Point3d::z <<endl;
}
输出结果为1,1,1,而不是正确的偏移地址。究其原因,应该是ostream对象没有重载类成员指针的参数,故不能正确输出偏移地址。而在VC下用<<输出中如果遇到不认识的类型,只要参数合法总输出1。
将上面的测试程序改变成一下程序便可以正确输出类中数据成员的偏移地址
int main(){
printf("%p\n",&Point3d::x );
printf("%p\n",&Point3d::y );
printf("%p\n",&Point3d::z );
return 0;
}
输出如下:
或者用如下测试程序也会输出相同结果:
int main(){
cout<<&((Point3d*)0)->x<<endl; //将0强制转化为Point3d指针,
cout<<&((Point3d*)0)->y<<endl; //然后去类成员便是他们的偏移地址
cout<<&((Point3d*)0)->z<<endl;
}
此外:由于目前的编译器的性质,可以用类成员指针来计算出相应类实例的大小:计算出最后一个数据成员的偏移量加上最后一个数据成员类型所占用的内存空间。
1.类成员指针不能做某些操作符的参数,如<和<<操作符
2.类成员指针是其相应成员的偏移地址
3.可以用类成员指针计算出类实例的大小