Skip to content

C++ 面向对象(OOP)与多态专题 ​

一句话总览 ​

OOP 三大特性:封装、继承、多态。C++ 面试 OOP 部分几乎都围绕 虚函数、多态实现、类内存布局、构造/析构 展开,且极喜欢面试官追问「为什么这么设计」。

class 本身的经典问题(struct/class 区别、特殊成员函数、copy-and-swap、类模板、陷阱速查)已汇总在 class.md;本页是问题清单式入口,细节按子文档下钻。

问题清单(含答案) ​

概念 / 特性 ​

1. 面向对象三大特性是什么?

答案

封装(隐藏实现、只暴露接口)、继承(复用 + is-a 关系)、多态(同一接口、不同实现)。

2. C++ 与其它语言 OOP 差异、struct vs class?

答案

struct 默认 public、class 默认 private;C++ 支持多继承、虚继承、RTTI、模板,Java 是单继承 + 接口。

3. 重载 / 重写 / 隐藏 的区别?

答案

重载(overload)同作用域同名不同参、编译期确定;重写(override)派生类覆盖基类虚函数、运行期多态;隐藏(hide)派生类同名函数遮蔽基类(非虚时即使签名不同也算隐藏)。

4. 默认生成的(五个/六个)特殊成员?

答案

默认构造、析构、拷贝构造、拷贝赋值、移动构造、移动赋值(移动只在没自定义拷贝/析构时默认生成)。三/五法则:自定义了拷贝/析构通常也要补全其余。

虚函数 / 多态(重点中的重点) ​

5. 什么是多态?编译期 vs 运行期?

答案

同一接口多种实现。编译期多态(模板、重载)编译期确定调用;运行期多态(虚函数)运行期通过 vtable 动态绑定。

6. vtable 与 vptr 的内存布局?

答案

含虚函数的类对象头部有一个 vptr,指向该类的 vtable(虚函数地址表)。vtable 每类一份、存于只读数据段;每个对象各持一个 vptr。详见 vtable.md。

7. 为什么析构函数要写成虚函数?为什么构造函数不能?

答案

基类指针 delete 派生类对象时,虚析构保证调到派生类析构,否则只析构基类部分 = 泄漏/UB。构造函数不能虚:构造时对象类型未"定形"(vptr 尚未指向派生类表),且虚构造无意义。

8. 纯虚函数、抽象类、接口类?

答案

virtual ... = 0 纯虚函数使类成为抽象类、不能实例化;全纯虚、无数据 = 接口类(类似 Java interface)。

9. 虚函数表存在哪里?一个类几个 vptr?

答案

vtable 在只读数据段(.rodata)。普通单继承一个 vptr;多继承每个非空基类子对象一个 vptr(可能多个)。

10. 基类指针 delete 派生类对象安全吗?

答案

只有基类析构是虚函数才安全;否则 UB(只释放基类部分、可能泄漏)。

11. 静态绑定 vs 动态绑定?

答案

静态绑定编译期确定地址(普通函数、非虚调用);动态绑定运行期经 vptr → vtable 间接跳转(虚函数),故有轻微开销但支持多态。

类内存 / 对象模型 ​

12. 空类大小?为什么是 1?

答案

1 字节,保证每个对象有唯一地址(&a != &b)。

13. 有虚函数后对象大小加了多少?vptr 放哪?

答案

加一个 vptr 的大小(64 位 8 字节),vptr 放在对象头部。

14. 多继承、菱形继承?

答案

多继承多个基类子对象依次排布、多个 vptr;菱形继承用虚继承,通过虚基类表(vbptr)共享唯一基类子对象,消除二义性。详见 inheritance-deep.md。

15. struct 布局要点?

答案

内存对齐(按最大成员对齐、中间补 padding)、位域(节省空间、按实现打包),见 memory/alignment.md。

子文档 ​

文件内容
class.mdclass 总览:struct/class/union、访问控制、特殊成员函数(0/3/5)、构造析构顺序、copy-and-swap、虚函数、类模板、陷阱速查
polymorphism.md多态机制、动态绑定
vtable.md虚表/虚指针内存模型、对象大小
virtual-destructor.md虚析构/构造辨析、特殊成员函数三/五规则
concepts.md重载重写隐藏、struct/class/union、访问控制
inheritance-deep.md多继承/菱形/虚继承布局与二义性、this、thunk
rtti-typeinfo.mdRTTI:typeid / dynamic_cast / type_info / -fno-rtti

糌粑的面经笔记 · VitePress 版