【发布时间】:2021-06-01 13:15:35
【问题描述】:
我了解 vptr 和 vtable 的概念以及它们在实现此机制中的作用。
编译器为每个具有至少一个虚函数的类构造一个vtable,并为每个类实例添加一个vptr指针,以便它可以访问vtable并在运行时执行正确的函数,但我无法理解究竟是如何。
考虑以下代码:
struct A
{
virtual void foo() { cout << "A::foo" << endl; }
virtual void goo() { cout << "A::goo" << endl; }
};
struct B
{
virtual void goo() { cout << "B::goo" << endl; }
virtual void foo() { cout << "B::foo" << endl; }
};
int main()
{
A *r = (A *)(new B());
r->foo();
}
输出:
B::goo
您能解释一下 B::goo 是如何以及为什么被处决的吗?编译器是否在编译时确定了在 vtable 中查找的位置? 谢谢。
编辑:
上面的代码sn-p只是一个例子,我认为可以让你理解我不理解的机制的哪一部分——很明显,我错了:)
请看下面的例子:
struct A
{
virtual void foo() {/* some implementation */}
virtual void goo() {/* some implementation */}
};
int main()
{
A *a = new A();
a->foo(); // <=====
}
对于这个例子,编译器构造了一个vtable,里面有两个函数指针,一个指向foo,另一个指向goo。 调用 foo 时,究竟发生了什么?编译器如何知道要使用哪个指针(在 vtable 中)?希望这说明清楚。
【问题讨论】:
-
reinterpret_cast经常导致 UB。 -
当我的机器尝试执行
r->foo();时崩溃了这就是 未定义行为 的好处,你看到的结果和我看到的结果一样好看到了。
标签: c++ dynamic-dispatch function-invocation