c++ - 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(); 陈述
解决方案
但我不明白我将如何描述语句 p->base::display(); 在vptr和vtable方面,编译器如何绑定基类版本的显示功能
Vptr 不以任何方式参与该调用。Vptr 仅用于虚拟调度。
在该调用中使用显式范围解析意味着您正在使用静态调度。您是说,base::display
无论对象参数的动态类型如何,都调用该函数。
虚拟调度是运行时多态的一种形式,也是面向对象编程的一个关键特性。当一个函数调用被虚拟分派时,调用被分派到继承层次结构中最派生的函数覆盖,这取决于对象的动态类型。
相反,静态分派的函数调用是使用编译时名称解析来分派的,它不受对象的动态类型的影响。这是 C++ 中使用的默认调度类型。它通常也是命令式、非面向对象语言(如 C)中唯一的调度类型。
虚拟调度只能与虚函数一起使用。虚拟调度通常使用虚拟函数表(vtable)和虚拟函数指针(vptr)来实现。
推荐阅读
- reactjs - 使用 apollo 客户端设置初始状态
- python - 使用正则表达式时出错。断言错误:得到
, 预期的 ` - javascript - 数组的属性如何
- java - 使用 FTP 将 Spring Boot app.jar 部署到 Azure 不起作用
- c# - 如何根据另一个属性从 json 列表中获取属性?
- django - 如何将 django 中的查询集转换为 json
- mysql - Mysql:如何在字符串列表中查找列值
- bash - 如何使用 Cadaver 上传名称中带有空格的文件?
- php - 在 PHP POST 表单中传递一个巨大的数组,以便基于这个数组创建一个 CSV 文件
- java - 如何修复 couchbase “获取对 rev hotel_4396 的错误响应 - > 错误的用户”