vptr和vtable如何在下面的虚拟相关代码中工作?

时间:2019-07-16 17:10:50

标签: c++ virtual-functions vtable vptr

据我所知,当我们在基类中使函数成为虚拟时,编译器将创建一个可称为vptr的指针,并且该表将保存虚拟函数的条目,该条目是该类的最新版本,以防被覆盖函数.vptr指向vtable。从基类派生的类具有相同的故事,它们具有指针vptr和自己的vtable,其中存放最新的虚拟函数的条目。要理解我的问题,请遵循代码

#include <iostream>
using namespace std;
class base
{
public:
virtual void display(void)
{
    cout << "base\n";
}
};

class derived : public base
{
public:
void display(void)
{
    cout << "derived\n";
}
};
int main(void)
{
    base *p;
    base ob1;
    derived ob2;
    p=&ob2;
    p->display();//my point starts from here
    p->base::display();

}

在上面的代码中,语句p-> display(); 确实有意义的是,对象p点调用了此类的vptr,并从vtable中查找显示功能并将其绑定。但是我不明白我将如何描述p-> base :: display();语句。就vptr和vtable而言,编译器将如何绑定基类版本的显示功能。因为在派生类的vtable中将没有基类版本的显示功能。 如果我知道的话在这里错了,请告诉我正确的是什么。如果我是对的,那么告诉我如何描述p-> base :: display();。我描述的逻辑的语句p-> display();声明

1 个答案:

答案 0 :(得分:4)

  

但是我不明白我将如何描述p-> base :: display();语句。就vptr和vtable而言。编译器将如何绑定基类版本的显示功能

Vptr完全不参与该调用。 Vptr仅用于虚拟调度。

在该调用中使用显式作用域解析意味着您正在使用静态调度。您是说,不管对象参数的动态类型如何,都调用函数base::display


虚拟调度是运行时多态的一种形式,并且是面向对象编程的关键功能。当虚拟地分派一个函数调用时,该调用将分派给继承层次结构中该函数最派生的重写,具体取决于对象的动态类型。

相比之下,静态调度的函数调用是使用编译时名称解析来调度的,不受对象的动态类型的影响。这是C ++中使用的默认调度类型。在命令式,非面向对象的语言(例如C)中,它通常也是唯一的调度类型。

虚拟调度只能与虚拟功能一起使用。通常使用虚拟功能表(vtable)和虚拟功能指针(vptr)来实现虚拟调度。