在C++对象模型中,Nonstatic data members被配置于每一个class object之内,static data members则被放在个别的class object之外。static和nonstatic function members也被放在个别的class object之外。
virtual functions则通过下面两个步骤来实现:
- 每一个class产生出一堆指向virtual functions的指针,放在表格之中。这个表格被称为virtual table(vtbl)。
- 每一个class object被安插一个指针,指向相关的virtual table。通常这个指针被称为vtpr。vtpr的设定和重置由每一个class的constructor、destructor和copy assignment运算符自动完成。每一个class所关联的type_info object(用来支持runtime type identification,RTTI)也经由virtual table被指出来,通常放在表格的第一个slot。
示例1:虚拟继承下的C++对象模型
在下面的代码示例中,Point3d和Vertex虚拟继承自Point2d,Vertex同时继承自Point3d和Vertex。
1 |
|
写这个示例的目的是为了验证:在Point3d的对象模型中有两个虚表指针,一个是从其基类Point2d那里继承而来的,另一个是Point3d自身的。
Point2d的对象模型:
Point3d、Vertex、Vertex3d的对象模型。
从上图可知,在Point2d中有两个float类型的成员变量和一个指针。故Point2d的大小为16字节;Point3d对象有一个Point2d子对象和一个float类型数据成员z、一个虚表指针Point3d,故大小为16+4+8 = 28,但是因为28不是8的倍数(在64位系统上运行的),所以28被边界对齐到32字节。同理Vertex的大小为16+8+8=32字节。对于Vertex3d,其大小为16+4+8+4+8+8 = 48字节。
示例2:继承模型下的地址
1 | class A { |
A、B和C的对象模型:
在将A类型的指针指向C类型的对象时,因为指针指向的实际上是C类型对象中的class A子对象。因为,在A和C类型对象中,A类型子对象都是位于相同的位置(位于对象开始处,偏移量为0),因此pA和pC的值相同。而在class C object中,B subobject的偏移量为8(即sizeof(A)),因此,pA和pC的值不同。