首页 > 解决方案 > vptr 和 vtable 在下面的虚拟相关代码中是如何工作的?

问题描述

据我所知,当我们在基类中创建一个虚拟函数时,编译器会创建一个可以称为 vptr 的指针,以及一个包含虚拟函数条目的 vtable,这些条目是此类的最新版本,以防被覆盖函数。并且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(); 陈述

标签: c++virtual-functionsvtablevptr

解决方案


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

Vptr 不以任何方式参与该调用。Vptr 仅用于虚拟调度。

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


虚拟调度是运行时多态的一种形式,也是面向对象编程的一个关键特性。当一个函数调用被虚拟分派时,调用被分派到继承层次结构中最派生的函数覆盖,这取决于对象的动态类型。

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

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


推荐阅读