CppCoreGuidelines C.128 必须指定虚函数为 virtual, override 或 final
10 December 2022
C.128: Virtual functions should specify exactly one of virtual
,
override
, or final
理由
更好的可读性。更快的检测到错误。明确指定是virtual
, override
或 final
,
可以更清楚的说明代码意图,让编译器捕捉到基类和继承类之间的类型不匹配错误。然而,添加两个以上这三个关键字就多余了,也容易导致错误。
简单的说:
virtual
只意味着“这是一个新的虚函数”override
只意味着“这是不是一个final
的重载”final
只意味着“这是一个final
的重载”
例子
struct B { void f1(int); virtual void f2(int) const; virtual void f3(int); // ... }; struct D : B { void f1(int); // bad (hope for a warning): D::f1() hides B::f1() void f2(int) const; // bad (but conventional and valid): no explicit override void f3(double); // bad (hope for a warning): D::f3() hides B::f3() // ... };
例子
struct Better : B { void f1(int) override; // error (caught): Better::f1() hides B::f1() void f2(int) const override; void f3(double) override; // error (caught): Better::f3() hides B::f3() // ... };
讨论
我们想避免某些类型的错误:
- 隐式的虚函数:程序员想设计一个函数为隐式的虚函数,事实上也是虚函数(但是读代码的人分辩不出来);或者程序员计划设计一个隐式的虚函数,但是其实上不是虚函数(比如因为某些席位的参数列表不匹配);或者程序员不想把一个函数设计成虚函数,但是其实上是虚函数(因为该函数刚好和基类的虚函数签名一致)。
- 隐式的重载:程序员计划设计一个函数是重载函数,事实上也是一个重载函数(但是读代码的人看不出来);或者程序员计划设计一个函数为重载函数,但是其实上不是(比如,因为某些细微的参数列表不匹配);或者程序员不想把一个函数设计成重载函数,但是其实上是一个重载(因为刚好该函数与基类的虚函数签名一致,注意,不论该函数是声明为虚函数还是非虚函数,这个问题都可能出现。因为程序员可能计划创建一个新的虚函数或者一个新的非虚函数)。
注意
当一个类被声明为 final
的时候,不管你把一个虚函数设置为 override
或
final
无关紧要了。
注意
减少使用 final
函数,因为 final
不会使得代码更好,只是防止被重载。
强化
- 比较基类和派生类中的虚函数名字,标记用了同一个名字,却不是重载的情况
- 标记没有用
override
或final
的重载函数 - 标记使用了一个以上
virtual
,override
和final
的函数声明