《深度探索C++对象模型》第3章 Data语意学

虚基类(其实只要是空类就行,文中以空虚基类为例)X会被安插1Byte的char,使它的对象可以在内存中被分配一个独一无二的地址。

①继承下来的Y、Z会添加一个指向虚基类子对象的指针或一个相关的表格(4Byte),再加上X的1Byte,4+1=5,再对齐填充为8Byte。

②但新的编译器(VC++和gcc)对空虚基类进行了特殊处理,被视为派生类开头的一部分,没有花费任何额外的空间,也就节省了1Byte,同时也节省了3Byte的对齐。


1.Data Member的存取

static data member存放在class object之外,可以直接访问,取地址时,会得到一个指向其数据类型的指针。如果两个类有同名的static member,编译器会为其名称编码,使二者名称不同。

nonstatic data member存放在每个class object中,存取由this指针完成,由object的地址和在class中的offset取得。


2.”继承“与Data Member

C++保证“出现在派生类中的base class subobject有其原样的完整性”,比如concrete1---派生--->concrete2---派生--->concrete3的对象布局如下:

否则,当发生concrete1 subobject的赋值操作时,就会破坏concrete2了,比如:

Concrete2 c2 = (Concrete1) c1;


单继承虚函数表分析:

 以下面的一对父类和子类为例:

  • 同类对象共享vtbl,但有各自的vptr
  • 如果子类没有新的(包括重写)虚函数,则父类与子类的vtbl内容相同,但所占用的内存空间不同
  • 无论父类或子类,(单继承时)都只会有一个vtbl,不要误以为子类中有:一个自己的vtbl+一个父类中的vtbl

多继承虚函数表分析:

  • 一个类如果有多个基类(基类有虚函数),则有多个vtbl,分别对应多个基类。子类新的虚函数加在第一个基类的vtbl中

菱形继承问题:

采用虚继承解决,使得X的对象只能取得一份A::data。

此时,X中存在两个虚基类表指针(vbptr),分别指向B、C中的虚基类表(vbtable),获得A::data相对于类B的offset,B的基址+B::offset得到B.A::data(或者获得A::data相对于类C的offset,C的基址+C::offset得到C.A::data)。

更多关于虚继承(虚基类表和虚基类表指针)的内容可参考下方博客。


参考博客:

posted @ 2023-05-03 14:30  Hell0er  阅读(26)  评论(0)    收藏  举报