在内存布局上,地址从低到高,顺序如下:派生类的虚函数表指针+虚基类表指针+派生类的成员变量+“间隔”(4个字节)+基类的虚函数表指针+基类的成员变量。派生类跟基类实例的位置关系跟普通继承正好相反。 说明:“间隔”产生的原因是派生类重写了基类的虚函数。如果没重写,则这一项没有。"本类地址"指的是包含有虚...
把Left和Right改成了虚拟继承Top。 从上面验证简单虚拟继承时,编译器安插虚表指针的例子,我们可以想象出此时Bottom类的对象内存布局如下: 对,你没有看错!虚拟继承时,子类只有父类共同继承的祖父类的一份存在。这其实也就是虚拟继承的最大用途。此时,Top,Left,Right和Bottom对象的大小分别为:4 ,12 ,12 ,24。
;从下面的内存布局图可以看到, 父对象 Left 的首地址和 Bottom 一样 ; 41 : b.j = 1; mov DWORD PTR _b$[ebp+4], 1;将 1 赋给偏移对象 b 首地址 4byte 处内存,即为 ;继承来的成员变量 j 赋值 1 ; 42 : bp->j = 2; mov mov 赋值 2 eax, DWORD PTR _bp$[ebp];将...
本节讨论不同的继承方式造成的不同内存布局。 2.1 C结构(struct) 由于C++基于C,所以C++也“基本上”兼容C。特别地,C++规范在“结构”上使用了和C相同的,简单的内存布局原则:成员变量按其被声明的顺序排列,按具体实现所规定的对齐原则在内存地址上对齐。所有的C/C++厂商都保证他们的C/C++编译器对于有效的C结构采...
2 类布局 本节讨论不同的继承方式造成的不同内存布局。 2.1 C结构(struct) 由于C++基于C,所以C++也“基本上”兼容C。特别地,C++规范在“结构”上使用了和C相同的,简单的内存布局原则:成员变量按其被声明的顺序排列,按具体实现所规定的对齐原则在内存地址上对齐。所有的C/C++厂商都保证他们的C/C++编译器对于有...
图1 菱形继承,所有类不含任何虚函数 下面是每个类的内存布局 Left(12byte) Right(12byte) Bottom(24byte) 上面代码中,Left和Right类对象首地址处都含有一个vbtable(误写为了vtable)指针,指向一个vbtable,vbtable里面只有两项:第一项是vbtable指针所属类的虚表指针vptr(没有就从对象首地址开始算)相对于vbtale...
C++内存布局之虚拟继承 虚拟继承 即派生类继承多次基类,但在派生类中只存在一份基类的拷贝。编译器实现虚拟继承的方式并不相同,下面我结合VS2010来探讨C++虚拟继承。声明一个虚基类CommonBase,两个从虚基类虚拟派生Base1和Base2,然后D,公有多继承自Base1和Base2,具体类定义如下:...
口试题中很轻易考,而涉及到类的时候,又不得不说类的继承,虚继承,虚函数,所以涉及到了类的内存布局,其中关于虚拟继承(virtual public)这个话题比拟难以懂得,而且不同的编译器环境可能实现的类的内存布局不同,所以本文仅在ms vs2010编译环境下调试,如果你在像cfree这样的编译器中调试结果会不同当涉及到虚拟继承的...
特别说明,GNU的GCC编译器在处理虚拟继承上跟VS有不同的地方。它的内存布局是:派生类的虚函数表跟虚基类表合并,另外分析。 另外,发现如果派生类实现了基类的虚函数,那么派生类对象,派生类和基类的实例之间会多出一个值为0的间隔。 //VS编译器--单个虚拟继承.cpp ...
其中,每一个类都有自己独有的一个虚函数,子类都会复写从父类继承而来的虚函数。 下面是main函数中的汇编码: ;60 : int main() {pushebpmovebp, espsubesp,84;为程序中的变量预留存储空间,其中对象b占用40byte;61 : Bottom b(1, 2, 3, 4);push1;压入标志,1表示调用虚基类构造函数 0表示不调用虚基...