虚拟成员函数(virtual member function)的调用

《深度探索C++对象模型》的读书笔记 问题域:由于实现虚拟函数机制将不可避免的打破对象与 C 的二进制兼容性, 需要仔细考虑哪些类才是需要增加虚拟函数机制的.理论上, 这个范围可以限定在那些必须支持运行期多态(runtime polymorphism)的类. runtime polymorphism 也被称为 active polymorphism, 例如:意图通过基类指针调用子类的 virtual function 实现, 即我们常常提及的多态.相对的, 可在编译期被解决的则称为 passive polymorphism. 例如, 通过子类实例或指针调用的, 通过class scope operator明确调用的virtual function. 对这类调用, 均将绕开虚拟函数机制, 被当作一般的成员函数进行处理. 这也是 inline virtual function 是有意义的原因.实际上, 由于编译器实现上的限制, 当类中包含 virtual member function, 即会加入虚函数机制 (即使主要使用方式是 passive polymorphism. 不过这本书出现这么久, 不知道现在编译技术发展如何?).调用的实现策略:
(具体方式因编译器而异)单继承1. 每个类均有自己的virtual function地址表格, 且只有一个.2. 该类的每个 virtual function 均被指派一个固定表格索引值 (仅对编译器有意义).       a. 每个虚函数的索引值在整个继承体系中保持不变       b. 当子类添加时 virtual function, 使用靠后的表格索引值 (在子类的 virtual function 地址表格中)       c.表格中只有active virtual function, 并非全部虚函数       d.纯虚函数的地址使用pure_virtual_called()或类似函数, 一个被调用时会终止程序的函数(按实现), 担当保护者的角色3. 在类的实例中增加指向表格的指针多重继承Derived 分别继承自 Base1, Base2.

子类中分别包含每个父类的virtual function table指针, 其中被子类改写的虚拟函数的地址已被重新设置. 子类实例的内存布局如下图:
(具体方式因编译器而异, 但包含的元素是一致的)Base1 subobjects  (Base1的成员变量)Base1 vptr        (Base1的virtual function table)Base2 subobjectsBase2 vptrDerived subobjectsDerived vptr (书里没写, 个人推测, 当子类具有新的虚拟成员函数时, 将出现其自身的virtual function table)1 .当使用"第一个"父类的指针调用时, 与单继承的情况相同.2. 当使用"第N个"父类的指针调用时 (N > 1), 将涉及两个动作       a.取得对应的virtual function table:
在子类指针转换为父类指针时, 已经按照内存布局进行了偏移计算, 于是可以正确得到virtual function table指针. 转换时的代码将类似于(假定N=2):
ptrBase2 = ptrDerived ? ptrDerived + sizeof(Base1) : 0;
b.将父类指针转换为子类指针, 作为函数参数传入:
由于父类指针是由子类指针+地址偏移得到的, 需要反向转换. 这里提到可以使用thunk技术实现高效转换.
3. 当使用子类指针调用时, 等于是passive polymorphism, 直接编译期解决...
这里仅列出了多重继承问题中我所理解的部分, 实际中还有:"当Base1, Base2有相同签名的虚拟成员函数时, Base1 vptr, Base2 vptr中的地址会被如何设置?", "私有继承, 公共继承混杂又如何"之类的问题. 所以, 珍惜生命, 远离多重继承......

原文链接: https://www.cnblogs.com/smart-mk1/archive/2011/02/25/1964847.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/21553

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月7日 下午11:31
下一篇 2023年2月7日 下午11:32

相关推荐