卡码笔记-最强八股文
首页
计算机基础
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

# C++如何禁止一个类被继承

面试官问"怎么禁止一个类被继承",大多数人能答出 final,但接着追问"final 除了禁止继承还能干什么""为什么要禁止继承""C++11 之前怎么做的",就开始含糊了。

这道题考的不只是语法,而是你对面向对象设计原则的理解——什么时候该用继承,什么时候该禁止继承。

# 简要回答

C++11 起,直接用 final 修饰类即可:class MyClass final { ... };。编译器在解析继承关系时发现目标是 final 类,直接报错,零运行时开销。C++11 之前需要用私有构造函数 + 虚继承 + 友元的组合 hack,复杂且已被淘汰。

# 详细回答

final 的两种用法

第一种是修饰类:class MyClass final { ... };,禁止任何类继承它。第二种是修饰虚函数:void speak() final;,禁止派生类重写这个虚函数。两者都是编译期静态检查,不产生运行时开销。

底层原理很简单——编译器在解析继承关系或虚函数重写时,检查目标是否标记了 final。如果是,直接报编译错误 cannot derive from 'final' base 或 cannot override 'final' function,不需要任何运行时机制。

C++11 之前的替代方案(了解即可,不推荐使用)

核心思路是利用虚继承的一个特性:虚继承要求最终派生类直接调用虚基类的构造函数。具体做法是定义一个辅助类 MakeFinal,把构造函数设为 private,然后让目标类虚继承它并声明为友元。这样目标类自己能构造(因为是友元),但如果有人试图继承目标类,最终派生类需要直接调用 MakeFinal 的私有构造函数,访问不到就报错了。

这个方案依赖复杂的继承关系和访问控制,可读性差、维护成本高,现在完全没必要用了。

C++ final禁止继承原理

# 知识拓展

Q:final 在性能上有什么好处?

编译器知道一个类是 final 或者一个虚函数是 final 后,可以做**去虚拟化(devirtualization)**优化。因为不可能有派生类重写这个函数,编译器可以在编译期确定调用目标,把虚函数调用(通过 vptr 间接跳转)优化成直接调用甚至内联。热路径上频繁调用的虚函数加 final 能有明显性能提升。

Q:什么场景下应该禁止继承?

工具类(只有静态方法,没有状态,继承没意义)、策略类(通过组合使用而非继承)、资源句柄类(如 FileDescriptor,继承可能破坏 RAII 语义)、性能关键类(加 final 帮助编译器优化)。核心原则是组合优于继承——如果一个类的设计意图是被组合使用而非被继承扩展,就应该加 final 明确表达这个意图。

Q:final 和 override 有什么关系?

两者都是 C++11 引入的上下文关键字,配合虚函数使用。override 告诉编译器"我确实在重写基类虚函数",写错签名会报错,防止隐式隐藏。final 告诉编译器"到此为止,不允许再重写"。两者可以同时使用:void speak() override final; 表示"我重写了基类的 speak,并且禁止后续派生类再重写它"。

Last Updated: 5/23/2026, 4:51:07 PM

← 多重继承的优缺点及菱形继承问题 深拷贝和浅拷贝的区别? →

评论

验证登录状态...

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