VC和GCC成员函数指针实现的研究(二)
接下来是多重继承,用到的测试代码如下所示:
VC多重继承成员函数指针实现
图八:VC多重继承的指针赋值操作
赋值的部分和单继承是一样的。
图九:VC多重继承的函数指针调用
调用的时候主要看(c.vptr2)()的代码。因为(c.vptr1)()生成的和单继承一样。而由于它们最终都转向vcall,所以vptr2的时候调整了虚表指针为c的第二个虚表。顺便*把this指针地址调整了。
但是在转入vcall之后的操作和单继承是一样的,都是跳转到 虚表+偏移地址 后执行。
但是c的虚表内记得地址不是直接记得foo_c::info的地址,因为要把this指针由foo_b转回foo_c。
图十:VC多重继承的虚表
(和前面不是同一批的截图,可能地址会对不上)
可以看到c和b的foo_b类型的虚表的info函数指向的地址是不同的。b中的foo_b虚表中的info函数直接指向了foo_b::info,但是c中的foo_b虚表里的info函数指向的地址先做了类型转换的地址调整,再才跳到foo_c::info,所以c的info的vcall跳过去后的代码是这样:
图十一:VC多重继承的vcall
(和前面不是同一批的截图,可能地址会对不上)
可以看到cx又减了8,把this指针由foo_b类型转回了foo_c。
执行结果也没什么特别的就不贴了。
GCC多重继承成员函数指针实现
图十二:GCC多重继承的函数指针赋值
哈,GCC的多重继承的赋值部分也和单继承一样,那么调用呢?
图十三:GCC多重继承的函数指针调用
如上图所示,比单继承多了两行,第一行是调整虚表地址到foo_b,这点和VC一样。后面增加的add指令是调整成员函数的this指针地址。
图十四:GCC多重继承的函数指针调用
(和前面不是同一批的截图,可能地址会对不上)
这个this指针的恢复的做法和VC是一样的,也是多一次跳转,然后把地址减回来。
Last updated