CppCoreGuidelines C.139 少用 final
29 December 2022
C.139: Use final
on classes sparingly
理由
通过 final
类限制继承层级没有什么太多逻辑上的理由,还会破坏继承层级的可扩展性。
例子
class Widget { /* ... */ }; // nobody will ever want to improve My_widget (or so you thought) class My_widget final : public Widget { /* ... */ }; class My_improved_widget : public My_widget { /* ... */ }; // error: can't do that
error: cannot derive from 'final' base 'main()::My_widget' in derived type 'main()::My_improved_widget' 16 | class My_improved_widget : public My_widget { /* ... */ }; | ^~~~~~~~~~~~~~~~~~
一开始你可能觉得不需要扩展优化My_widget
,但是等到后来需要扩展的时候,就会报错。
注意
并非所有的类都用来做基类。比如大部分的标准库的类。如 std::vector
,
std::string
就不是用来派生子类的。这条规则也适用于那些有虚函数、用来做接口的类层级。
注意
把单个的虚函数限制为 final
也容易出错,因为人们很容易忽视 final
的存在,然后发现出错了。当然,编译器可以捕捉这类错误,所以你也不能在派生类中重新什么或重新打开一个 final
成员函数。
号称 final
能提升性能也缺少根据。通常是基于其他编程语言的经验推导出来的。
当然有时候使用 final
也有逻辑上和性能上的重要原因。一个例子是对编译器和分析语言工具来说性能关键的 AST 继承层级。新的派生类不会时不时的出现,而且新的派生类只能通过库的实现者来添加。然而,误用 final
的例子还是会更多一些。
强化
- 标注用了
final
的类