目录
一、Data Member的绑定(The Binding of a Data Member)
二、Data Member的布局(Data Member Layout)
五、对象成员的效率(Object Member Efficiency)
六、指向Data Members的指针(Pointer to Data Members)
先从一个例子开始,假如给定以下class的定义及继承关系:
class X { };
class Y : public virtual X { };
class Z : public virtual X { };
class A : public Y, public Z { };
则分别对class X,class Y,class Z和class A求sizeof()的值是多少?
答案可能不那么直观,因为乍一看这几个类都没有任何成员,所以应该都是空的,但实际上,在作者的编译器上sizeof()的结果分别是:
sizeof(X) == 1;
sizeof(Y) == 8;
sizeof(Z) == 8;
sizeof(A) == 12;
(而侯捷老师在VC++5.0上测试的结果分别为1,4,4,8,这其实是因为新一点的编译器对empty virtual base class做了优化处理)
class X的大小是1的原因是:编译器会在empty class的对象里安插进一个字节的大小,目的是保证这个class的两个对象得以在内存中配置独一无二的地址。
class Y和Z的大小受到三个因素的限制:(1)语言本身所造成的额外负担。虚继承机制会在派生类中安插一个指针,这个指针要么指向virtual base class subobject,要么指向一个表格,表格中放的要么是virtual base class subobject的地址,要么是它的偏移位置。(2)编译器对于特殊情况的优化处理。如果没有对empty virtual base class做优化处理,也会在派生类的固定部分的尾端插入一个多余的字节,因为派生类也是空的;如果对empty virtual base class做了优化处理,这一个多余的字节就不需要插入,原因是一个empty virtual base class 被视为derived class object的开头一部分,所以derived class object相当于拥有了成员,也就不需要那额外的一个字节了,而empty virtual base class的大小又不会算进derived class object里去,所以derived class object的大小就是一个指针的大小。(3)内存对齐的需要。
class A的大小的分析与Y、Z类似。如果没有对empty virtual base class做特殊处理,class A中将包括:被大家共享的唯一的一个class X的实例,大小为1;class Y和class Z去掉class X后的大小,各为4,加起来是9,4字节对齐以后答案就是12。如果对empty virtual base class做了特殊处理,那么class X的1个字节会被拿掉,连带着内存对齐补齐的3字节也被拿掉,答案为8个字节。
一、Data Member的绑定(The Binding of a Data Member)
看下面的代码:
extern float x;
class Point3d
{
public:
Point3d( float, float, float );
//问题:被传回和设定的x是哪一个x呢?
float X() const { return x; }
void X( float new_x ) const { x = new_x; }
//......
private:
f