gpt4 book ai didi

c++ - 为什么 C++ RTTI 需要虚拟方法表?

转载 作者:行者123 更新时间:2023-12-01 14:51:45 25 4
gpt4 key购买 nike

为什么 C++ RTTI 要求类有一个虚拟方法表?虽然使用表作为多态向上转换的手段似乎是合理的,但从设计的角度来看,它似乎并不是严格要求的。例如,该类可以包含传递信息的散列或唯一标识符。
对于认为这个问题过于琐碎的 C++ 专家,这将有助于这个问题的发帖者(他是 C++ 的一个谦逊的初学者)从 RTTI 的设计角度解释为什么需要 vtables,以及什么是其他设计方法(而不是使用 vtables)来实现 RTTI(以及它们为什么工作/不工作以及 vtables)。

最佳答案

从语言的角度来看,答案是:它不是 . C++ 标准中没有任何地方说明如何实现虚函数。编译器可以自由地确保调用正确的函数,但它认为合适。
那么,通过替换 v 可以获得什么?指针 (不是 v )具有 id 并删除 vtable? (用 id 替换 vtable 并没有任何帮助,一旦你解决了 vptr,你就已经知道运行时类型了)
运行时如何知道实际调用哪个函数?
考虑:

template <int I>
struct A {
virtual void foo() {}
virtual void bar() {}
virtual ~A() {}
};

template <int I>
struct B : A<I> {
virtual void foo() {}
};
假设你的编译器给出 A<0> ... 让我们称之为 视频 ... 0 和 A<1>视频 1. 请注意 A<0>A<1>在这一点上是完全不相关的类。如果你说 a0.foo() 会发生什么?在哪里 a0A<0> ?在运行时,非虚拟函数只会导致静态调度 call .但是对于虚函数,调用函数的地址必须在运行时确定。
如果你只有 vid 0,你仍然需要编码你想要的功能。这将导致 if-else 分支的森林,以找出正确的函数指针。
if (vid == 0) {
if (fid == 0) {
call A<0>::foo();
} else if (fid == 1) {
call A<0>::bar();
} /* ... */
} else if (vid == 1) {
if (fid == 0) {
call A<1>::foo();
} else if (fid == 1) {
call A<1>::bar();
} /* ... */
} /* ... */
这将失控。因此,表。添加标识 foo() 的偏移量以 A<0> 为基数的函数的 vtable 并且您有要调用的实际函数的地址。如果您有 B<0>相反,将偏移量添加到该类的表的基指针。
理论上,编译器可以为此发出 if-else 代码,但事实证明,指针添加速度更快,生成的代码更小。

关于c++ - 为什么 C++ RTTI 需要虚拟方法表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63025648/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com