0

dynamic binding中,函数调用根据指针指向的对象类型绑定到函数实现。

假设我们有以下代码:

base *bptr = new derived;
bptr->func();

让函数func在基类中声明为虚拟的。func然后,由于动态绑定,派生类的虚函数版本将在运行时被调用。

我理解上面的概念。

但是我在研究了上述概念后对以下概念感到困惑。

在上面的代码片段中,指向派生类对象的指针被隐式转换为指向基类对象的指针。那么bptr将实际指向派生类对象的基类子对象,而不是指向派生类对象。

由于基类指针bptr指向基类子对象,在运行时不应该func调用基类的虚函数版本吗?

4

3 回答 3

3

您似乎错过了动态绑定的实际含义。这意味着即使指针(静态)引用基本子对象,调用也将被分派到完整对象的(动态)类型。

常见的实现是通过一个虚函数表。基本子对象将作为隐藏成员存储指向它所属的实际完整类型的虚函数表的指针。所有对虚拟函数的调用(未禁用动态调度)都通过额外的间接级别进行路由,以确保最终的覆盖将被调用。

至于如何管理该表和隐藏指针的细节,编译器为每种类型的虚拟函数构建 e 表,并将代码注入不同的构造函数以相应地更新指针。因此,在构建基础子对象时,指针引用基础 vtable,但在进入派生构造函数之前,注入的代码将更新指针(在基础中)以引用派生 vtable。

于 2012-01-27T12:56:22.470 回答
1

不要为此感到困惑。“指向派生类对象的指针被隐式转换为指向基类对象的指针”——这句话的意义在于假设derived有一些方法derivedOnly(),而base. 现在,如果您尝试bptr->derivedOnly();,那么即使您确实引用了derived.

所以,bptr确实是一个指向base.

于 2012-01-27T12:57:00.667 回答
0

在这个例子中:

base *bptr = new derived;
bptr->func();

该类base只是以某种方式用作接口以了解可以调用哪些方法,因为它指向派生对象实例。vtable (http://en.wikipedia.org/wiki/Virtual_method_table) 将使derived类中的方法被调用。

于 2012-01-27T12:53:48.270 回答