本文参考深度探索C++对象模型
我们常常使用基类指针指向派生类对象,那么,为什么基类指针能够如此轻松的调用派生类的方法呢?在多继承的情况下,this指针必须经过调整,才能正确地找到虚表。下文为你介绍多继承模型下的指针偏移机制
设一个多继承的类内存布局如下,单词代表对象首地址。(派生类假设无额外成员)
后[Derived[BASE1][BASE2]]前
有三种情况,指针会发生偏移。
使用基类指针指向派生类
赋值时:派生->基
派生类的指针转型为第二个基类指针。向前调整Base1长度以正确指向Base2。
调用时:基->派生
指向第二个基类的指针,调用派生类的虚函数。例如:对于Base1和Base2而言,如果Base2定义clone,Derived重写了clone,那么需要向后调整Base1长度以正确指向Derived object
使用派生类指针指向派生类
调用时:派生->基 指向派生类的指针,调用第二个基类继承来的虚函数。向前调整Base1长度以正确指向Base2 sub-object。
1.赋值:转型
temp为已知Derived指针。
Base2 * pbase2 =temp ? temp + sizeof (Base1):0;
目的是防止temp==nullptr时,仍然出现偏移。
2.调用:
split functions
address points:
虚函数期待获得的是引入虚函数的类对象的地址(而非派生类),这就是这个函数的address point。换而言之,它首先确保了转入的地址能够正确的指向对应的调用对象,此后再进行传递。