c++中如何使用final关键字_c++禁止类继承或虚函数重写【汇总】

final关键字用于禁止类被继承或虚函数被重写,是编译期强制约束;类名后加final禁止继承,虚函数声明末尾加fi

nal禁止重写,仅适用于虚函数且不可用于定义、非虚函数或构造/析构函数。

final 关键字在 C++11 中引入,作用很明确:禁止类被继承,或禁止虚函数被重写。它不是修饰符“开关”,而是编译期强制约束,写错会直接报错。

final 禁止类被继承

在类名后加 final,该类不可作为基类:

class Base final {
public:
    virtual void func() {}
};

此时若尝试继承:

class Derived : public Base {}; // 编译错误:cannot derive from 'final' class
  • 必须紧贴类定义末尾,不能放在访问说明符后(如 public final class Base 是非法的)
  • 模板类也可用 final,但实例化后才检查是否被继承(即派生类模板实例化时才报错)
  • delete 构造函数不同:final 阻止的是继承关系本身,不阻止对象创建

final 禁止虚函数被重写

在虚函数声明末尾加 final,子类中同签名函数将无法重写:

class Base {
public:
    virtual void func() final {} // 注意:final 在函数声明末尾
};

子类中试图覆盖会失败:

class Derived : public Base {
public:
    void func() override {} // 编译错误:function marked 'final' cannot be overridden
};
  • final 只能用于虚函数(含纯虚函数),对非虚函数加 final 是语法错误
  • overridefinal 可同时出现,顺序不限,但 final 必须在声明结尾(virtual void f() override final; 合法)
  • 如果父类函数是 final,子类中即使不写 override,只要函数签名匹配,也会触发错误

final 的常见误用和陷阱

它不提供运行时保护,也不影响对象布局或性能 —— 完全是编译器语义检查工具。

  • 不能用于普通成员函数、静态函数、友元函数或构造/析构函数(除非是虚析构函数)
  • 不能用于函数定义(仅声明),如下写法错误:
    virtual void func() final { /* ... */ } // 声明处可,定义处不可
  • 头文件中使用 final 会影响 ABI:一旦加了 final,后续版本若想取消继承限制,必须移除 final 并重新编译所有依赖代码
  • sealed(C++/CLI)或 Java 的 final 行为相似,但 C++ 中无运行时等价机制

真正容易被忽略的是:当你在大型继承体系中给某个中间类加 final,可能破坏下游模块的扩展能力,而错误只在第三方派生时才暴露 —— 所以 final 更适合用于明确设计为“终端”的类型,比如 std::string_view 这类轻量值类型,而非通用基类。