卡码笔记-最强八股文
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
代码随想录 (opens new window)
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
代码随想录 (opens new window)
  • 本栏必读

    • 关于本专栏
    • C++学习路线
    • C++面试题系优化
  • 基础与语法

  • 面向对象

    • C++构造函数有几种,分别什么作用?
    • 什么是构造函数和析构函数?构造函数和析构函数可以是虚函数吗?为什么?
    • C++的重载和重写,以及它们的区别和实现方式
    • C++怎么实现多态
    • C++中的虚函数和纯虚函数有什么区别?
    • 虚函数怎么实现的?
      • 简要回答
      • 详细回答
      • 知识拓展
    • 多重继承的优缺点及菱形继承问题
    • 如何禁止一个类被继承
    • 深拷贝和浅拷贝的区别?
    • this指针的原理
    • C++如何实现一个单例模式?
  • STL 与容器

  • 内存管理

  • C++11 与现代 C++

  • 智能指针

  • 并发与 I/O

# 虚函数的实现机制

面试官问:"虚函数是怎么实现的?调用一个虚函数的时候底层发生了什么?"

这题考的不是"什么是多态",而是多态背后的实现细节。很多人能说出"虚函数表"三个字就卡住了,说不清vtable在哪、vptr什么时候初始化、调用链路是怎么走的。把这条链路讲清楚,这题就拿满分。

# 简要回答

编译器为每个含虚函数的类生成一张虚函数表(vtable),表里存的是该类各虚函数的地址。每个对象内部有一个隐藏的虚指针(vptr),指向所属类的vtable。通过基类指针调用虚函数时,运行时沿着 对象 → vptr → vtable → 函数地址 这条链路找到真正要调用的函数,这就是动态绑定。

# 详细回答

vtable:每个类一张表

编译器看到一个类里有virtual函数,就会为这个类生成一张vtable。表里按声明顺序存放各虚函数的地址。派生类如果override了某个虚函数,它的vtable里对应位置就换成自己的函数地址;没override的槽位继续指向基类版本。

vptr:每个对象一个指针

每个含虚函数的对象,内存布局里都多一个隐藏成员——vptr。构造函数执行时,编译器自动把vptr设置为指向当前类的vtable。所以Base* p = new Derived(),p指向的对象里的vptr指向的是Derived的vtable,不是Base的。

调用链路

p->show() 在底层展开为:取对象的vptr → 在vtable中按偏移找到show的地址 → 跳转调用。整个过程多了一次指针解引用(间接寻址),这就是虚函数比普通函数调用慢一点的原因。

核心就一句话:vtable让"调哪个函数"变成了运行时查表,而不是编译时写死。

虚函数实现机制

# 知识拓展

面试官可能追问:

Q1: vptr放在对象的什么位置?

主流实现(GCC/Clang/MSVC)都把vptr放在对象内存的最前面,这样通过对象首地址就能直接拿到vptr,不需要额外偏移计算。

Q2: 多继承时vtable怎么处理?

多继承时一个对象可能有多个vptr,每条继承链一个,对应多张vtable。通过不同基类指针调用虚函数时,走的是不同的vptr和vtable。

Q3: 虚函数调用比普通函数慢多少?

多一次指针解引用,通常就是一条mov加一条间接call的开销。现代CPU有分支预测和缓存,实际性能差距很小。真正的代价是编译器无法内联虚函数调用,丧失了内联优化的机会。

Q4: 为什么基类析构函数要声明为virtual?

delete basePtr时,如果析构函数不是virtual,只会调用基类的析构函数,派生类的析构不会执行,派生类申请的资源就泄漏了。声明为virtual后,析构也走vtable查表,能正确调到派生类析构。

Last Updated: 5/25/2026, 3:50:35 PM

← C++中的虚函数和纯虚函数有什么区别? 多重继承的优缺点及菱形继承问题 →

评论

验证登录状态...

侧边栏 侧边栏
夜间模式 夜间
卡码简历 卡码简历
代码随想录 代码随想录
卡码投递表 卡码投递表🔥
2026实习校招群 2026群
添加客服微信 2026实习校招客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记 支持卡码笔记
鼓励/支持/赞赏Carl 卡码笔记赞赏码
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪