非覆盖虚拟函数的绑定类型



考虑基类中的一个virtual function是派生类中的not overriden的情况。然后使用base class pointer to a derived class object调用虚拟函数。

我知道函数调用将在编译时解析为基类中的函数。

问题

由于函数在派生类中没有被重写,因此函数调用会在编译时绑定到函数实现吗?还是会将绑定延迟到运行时?

很可能会在编译时解决
大多数现代编译器都足够聪明,可以在编译时解决动态调度问题,前提是有足够的可信信息供他们决定。
在这种情况下,由于Derived类中没有提供重写函数,因此智能编译器应该能够在编译时静态解析函数调用。

为了能够在编译时猜测实现,编译器必须知道指向对象的类型。。。例如

MyBaseClass *p = new MyDerivedClass;
p->foo();

在上面的例子中,编译器应该足够聪明,能够猜测指向对象的类型,并且调度(假设编译器使用VMT解决方案进行后期绑定)应该不需要VMT查找,即使方法是虚拟的。

然而,例如在以下中

void doit(MyBaseClass *p)
{
    p->foo();
    ...
}

CCD_ 4的代码不能知道所指向的对象的类型,因此该调用将需要VMT查找。请注意,C++语言的设计使编译器可以一次工作一个编译单元,因此编译器不可能知道程序中只有一个派生类型(另一个模块的源代码可以定义不同的派生类,即使是在本地未命名的命名空间中,函数也会被重写)。

当然,函数doit最终可能会被编译器内联,因此如果可以推断类型,调用doit的特定调用站点可能确实不需要查找。但是,如果doit函数是公开可见的(例如,它不在未命名的命名空间或静态自由函数中),则当从其他编译单元调用时,为其生成的机器代码将包括VMT查找。

请注意,在所有关于何时需要查找的讨论中,如果虚拟函数是否已被覆盖,则完全无关。原因是,如果虚拟函数没有被覆盖,并且调度是用VMT实现的,那么派生类VMT将在该槽中具有基本实现的地址。

换句话说,p->foo()被编译为

 p->__VMT__[__FOO_VMT_SLOT_NUMBER__](p);  // Dynamic dispatch

 __DERIVED_FOO_IMPLEMENTATION__(p); // Type known at compile time

其中CCD_ 9是存储在VMT中的函数指针,并且它可以等于基实现的地址。

相关内容

  • 没有找到相关文章

最新更新