C++ 虚表起源

本文会让看不见 摸不着的虚表(Vtable),虚指针(Vptr)彻底现行

本文涉及思想:

C++ 面向对象 封装 继承 多态 中的 多态

概念解释:

虚表指针:

这是指向虚表(vtable)的指针,虚表中包含了该类的所有虚函数对应的地址。

虚表:

虚表是一个编译时生成的静态数组,存放在程序的数据段中,包含所有虚函数的地址(不属于类对象,与类对象无关)。每个类有自己的虚表,派生类可以继承基类的虚表并进行修改以反映任何虚函数的覆盖(重写)。

sizeof的严格语义:

A a;

sizeof(A)sizeof(a) 都表示类对象的大小,但它们从语法上指向稍有不同的含义:

sizeof(A):这表示测量 A 类型的对象所占用的内存大小,即类 A 的实例化对象的大小。这是从类型层面进行的测量,表明创建一个该类型的实例所需的字节数。

sizeof(a):这表示测量已经实例化的对象 a 的大小,其中 aA 类的一个实例。这实际上将给出与 sizeof(A) 相同的结果,因为 aA 类型。

如果一个类是空的,那么它占1字节,为了防止类对象重叠.

例如新建10个类,如果大小是0,内存中无论是顺序还是随机,都有概率会使用相同的内存地址

#include <iostream>

using namespace std;

class A
{
public:
};

int main()
{
    cout << sizeof(A) << endl; // 1
    return 0;
}

放入一个普通函数,不会改变类对象大小:

类对象的行为属于类的共享资源,存储在代码段中

#include <iostream>

using namespace std;

class A
{
public:
    void show(){};//虚函数和普通函数都不占类对象大小
};

int main()
{
    cout << sizeof(A) << endl; // 1
   
    return 0;
}

放入一个虚函数,则编译器会为该类创建一个虚指针,64位机器为8字节

#include <iostream>

using namespace std;

class A
{
public:
    virtual void show(){}; // 虚函数和普通函数都不占类对象的大小
};

int main()
{
    cout << sizeof(A) << endl; // 64位系统 Vptr占8字节

    return 0;
}

为了验证上述猜想:

#include <iostream>
using namespace std;
class A
{
public:
    virtual void show1()
    {
        cout << "666" << endl;
    }
    virtual void show2()
    {
        cout << "666" << endl;
    }
    virtual void show3()
    {
        cout << "666" << endl;
    }
};

int main()
{
    A a;
    cout<<sizeof(A)<<endl;//始终只存在1个虚指针,类对象大小为8字节
    a.show1();
    a.show2();
    a.show3();
    return 0;
}

无论放几个虚函数,始终只存在一个虚指针

借上面例子->这个虚指针指向一个虚表:

这个虚表就是一个函数指针数组 存放了show1,show2,show3的地址,也是C++实现多态的核心机制

下面我们要在GDB中观察到这4个地址:

g++ -g -o c2 c1.cpp
gdb c2
(gdb) break main
(gdb) run
(gdb) info vtbl a
写了几个虚函数看见几个地址就行

引入C++中两种不同的地址表示方式:

info symbol <> 或 info line <>   通常表示全局地址
info vtbl                                     表示相对于对象实例的地址

 所以可以理解为是两套地址系统,互相不能转换,通过全局的方式观察 show2并不是0x0

这样我们就看见了,也感受到了迷雾中的虚表(Vtable)和虚指针(Vptr)的存在

全剧终.

相关推荐

  1. C++ 函数

    2024-04-24 16:58:01       47 阅读
  2. c++ | 动态编译|函数函数

    2024-04-24 16:58:01       36 阅读
  3. [c/c++] 关于函数

    2024-04-24 16:58:01       56 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-24 16:58:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-24 16:58:01       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-24 16:58:01       82 阅读
  4. Python语言-面向对象

    2024-04-24 16:58:01       91 阅读

热门阅读

  1. OneFlow概念清单、以及优缺点

    2024-04-24 16:58:01       36 阅读
  2. JUC与多线程基础详解

    2024-04-24 16:58:01       32 阅读
  3. spring boot 定义启动页 到 login

    2024-04-24 16:58:01       31 阅读
  4. Python技术:从入门到精通的指南

    2024-04-24 16:58:01       26 阅读
  5. 【QEMU系统分析之启动篇(十五)】

    2024-04-24 16:58:01       25 阅读
  6. 39、Lua 中调用C函数(lua-5.2.3)

    2024-04-24 16:58:01       33 阅读
  7. 基于Hadoop的石油大数据平台设计

    2024-04-24 16:58:01       31 阅读
  8. css中backface-visibility使用

    2024-04-24 16:58:01       37 阅读
  9. docker 故障解决

    2024-04-24 16:58:01       39 阅读