如何控制虚拟表中虚函数的顺序?它们是否按照声明的顺序排列?
当继承具有虚拟表的类时,继承类的虚拟表是基类的扩展,或者是仅使用继承类虚函数创建的全新虚拟表。 (即虚拟表是否仍在该类的索引+ 0x0处?)
答案 0 :(得分:7)
这是完全实现的定义。 C ++标准根本没有指定任何类型的虚函数表 - 这就是它通常的实现方式。
答案 1 :(得分:7)
(a)就标准而言,你不能,(实际上你甚至不能假设vtable存在)。 (b)可能,但您需要控制订单的情况是什么,但您无法自行检查?检查的方法是查看虚拟调用的反汇编(并找到添加到vtable指针以获取调用地址的偏移量)或查看vtable本身的反汇编。
取决于。对于单继承,它可能是基类的扩展,每个对象的索引0指向该类的虚拟表,指向基类中声明的每个虚函数的正确实现(可能是覆盖),后跟指向派生类中声明的每个虚函数的指针。对于多重和虚拟继承,它不是(不可能)那么简单。每个对象都包含几个指针,可以是vtable,也可以是包含vtable和其他类信息的结构,当你围绕类层次结构转换时,对象的指针值会发生变化。试一试,看看。
所有这一切都是为了一个非常假设的“典型实施”。编译器编写者有他们的技巧。
答案 2 :(得分:2)
虚拟表是特定于实现的。它可以按任何顺序排列。甚至可能根本没有虚拟表来实现多态性。我推荐维基百科上的 this 文章,其中提供了一些问题的答案。
答案 3 :(得分:1)
虽然肯定100%正确,但其他答案忽略了一个明显的事实。
这不是一个愚蠢的问题,取决于海报的目标。我们经常被迫使用特定于平台的技术来实现我们的目标。特别是,海报试图做的事情与Windows上的COM非常相似......编写可以从中派生的纯虚拟抽象接口是获得防弹C ++ DLL而不退回到C接口的少数几种方法之一。
我在用原生C ++编写插件架构时遇到了同样的问题 - 缺少ABI意味着互操作非常令人沮丧。
答案 4 :(得分:0)
你的问题真的要问的问题是你需要以特定的顺序获得vtable的原因是什么?
这是依赖于实现的原因之一是因为编译器可能出于性能原因或特定于给定CPU体系结构的其他要求而选择如何布置vtable。