C++ 面试题 目录

C++ 中虚函数表 (vtable) 和虚指针 (vptr) 的概念

推荐答案

在C++中,虚函数表(vtable)和虚指针(vptr)是实现多态性的关键机制。

虚函数表(vtable)

  • 定义:虚函数表是一个存储类中虚函数地址的数组。每个包含虚函数的类都有一个对应的虚函数表。
  • 作用:当调用一个虚函数时,编译器通过虚函数表来查找并调用正确的函数实现。
  • 存储位置:虚函数表通常存储在只读数据段(.rodata)中。

虚指针(vptr)

  • 定义:虚指针是一个指向虚函数表的指针。每个包含虚函数的类的对象都有一个虚指针。
  • 作用:虚指针用于在运行时确定调用哪个虚函数。
  • 存储位置:虚指针通常存储在对象的内存布局的开头部分。

示例代码

-- -------------------- ---- -------
----- ---- -
-------
    ------- ---- ------- - --------- -- ------------- -- ---------- -
    ------- ---- ------- - --------- -- ------------- -- ---------- -
--

----- ------- - ------ ---- -
-------
    ---- ------- -------- - --------- -- ---------------- -- ---------- -
    ---- ------- -------- - --------- -- ---------------- -- ---------- -
--

--- ------ -
    ----- - - --- ----------
    -----------  -- --- --------------
    -----------  -- --- --------------
    ------ --
    ------ --
-

本题详细解读

虚函数表的工作原理

  1. 虚函数表的创建:当一个类包含虚函数时,编译器会为该类生成一个虚函数表。这个表包含了该类所有虚函数的地址。
  2. 虚指针的初始化:当创建该类的对象时,对象的虚指针会被初始化为指向该类的虚函数表。
  3. 函数调用:当通过基类指针或引用调用虚函数时,编译器会通过虚指针找到虚函数表,并从表中查找对应的函数地址进行调用。

虚指针的作用

  • 动态绑定:虚指针使得C++能够在运行时确定调用哪个函数,从而实现动态绑定(即多态性)。
  • 对象内存布局:虚指针通常位于对象内存布局的开头,这使得编译器能够快速访问虚函数表。

虚函数表的存储

  • 只读数据段:虚函数表通常存储在只读数据段中,以防止程序在运行时修改虚函数表的内容。
  • 每个类一个表:每个包含虚函数的类都有自己的虚函数表,派生类会继承基类的虚函数表,并在需要时进行扩展或覆盖。

示例代码解析

  • Base类Base类有两个虚函数func1func2,编译器会为Base类生成一个虚函数表,表中包含这两个函数的地址。
  • Derived类Derived类继承了Base类,并重写了func1func2Derived类的虚函数表会覆盖Base类中对应的函数地址。
  • 多态调用:在main函数中,通过Base类指针调用func1func2时,实际调用的是Derived类中的实现,这是因为虚指针指向了Derived类的虚函数表。

通过虚函数表和虚指针,C++实现了运行时多态性,使得程序能够在运行时根据对象的实际类型调用正确的函数。

纠错
反馈