C++动态调度机制及调用正确函数的过程

我了解 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 中查找的位置?谢谢。

编辑:

上面的代码片段只是一个示例,我认为它可以让您了解我不理解机制的哪一部分 - 显然,我错了 🙂

请看下面的例子:

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 中)?希望这能说明问题。

回答

您的示例具有未定义的行为:尝试通过指针对对象进行别名时,您违反了严格的别名规则。BA

与未定义的行为一样,所有的赌注都没有了,对程序行为的任何进一步分析都是徒劳的。

  • @katkato That is a compiler specific detail, but often the vtable entries are in the order the virtual functions are first declared. In your code, `r->foo()` wants to call the first virtual function (because `foo` is first in `A`). With `r` pointing to a `B`, it looks this up in B's vtable and finds `B::goo`, which, since it has the same signature, might just work in this instance.

以上是C++动态调度机制及调用正确函数的过程的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>