一、前言
昨天在公司做代码扫描,发现很多类似以下的代码都产生了告警,导致扫描不通过:
1 |
virtual int func() override {} |
不通过的原因是:同时使用 virtual 和 override 关键字来修饰成员函数,virtual 关键字是多余的,要删掉。
说实话,刚开始看到错误提示的时候有点懵,因为对这个特性并不是很了解 (代码也不是我写的),所以一时之间也不知道到底是什么原因,只是贸然按照提示把 virtual 关键字删掉了 (删掉了就好了),回来研究了一阵之后才搞明白。
二、 override 和 final
2.1 用途
override 和 final 是 C++11 中的新特性,主要用于类继承时对虚函数的控制:
- override 修饰子类成员函数,表明当前成员函数覆盖了父类的成员函数。
- final 修饰父类成员函数,表明当前成员函数不能被覆盖。
其实看到这里我心里有一个疑惑:加了 virtual 关键字就可以实现覆盖了,为什么要用 override 呢?C++ Primer 对这个问题的解释是:
派生类可能定义了一个和父类名字相同但是形参列表不同的成员函数,对编译器而言这不是非法的,这可能就导致不可预期的错误。可能我们是想覆盖父类的函数,但是因为不小心弄错了,最后编译器也没能帮我们检查出来。
加上 override 关键字之后,如果子类的函数在父类没有相同的函数名以及形参定义,编译器会报错。这就避免了因为开发人员不小心导致的意外错误。
因此,总结来看,override 的作用主要是:
- 减少程序员因为大意出错的可能性
- 提高代码可读性,读代码的人一看到 override 就能直观的知道当前函数是覆盖了父类的虚函数
2.2 示例
1 2 3 4 5 6 7 8 9 10 11 |
class Hero { public: virtual void SkillR(Hero &b) {}; }; class Soldier : public Hero{ public: Soldier() {} void SkillR(Hero &b) override {} }; |
以上定义了一个英雄类和一个继承于它的战士类,战士类继承了父类的 R 技能 SkillR(),它的函数名和形参列表和父类一模一样,加上 override 之后是没有问题的。但是如果把 SkillR 的形参去掉,编译时就会报错。
1 2 3 4 5 |
override.cpp:15:19: error: non-virtual member function marked 'override' hides virtual member function override.cpp:8:18: note: hidden overloaded virtual function 'Hero::SkillR' declared here: different number of parameters (1 vs 0) virtual void SkillR(Hero &b) {}; ^ 1 warning and 1 error generated. |
三、 override 和 virtual
回到问题本身,为什么 virtual 碰到 override 会失效?
当我使用 clion 编写上面的 IDE 也提示 virtual 是多余的:
原因:
cppreference.com 中找到 override 的定义为:
Specifies that a virtual function overrides another virtual function.
意思是说,override 指定函数是一个覆盖了其他类虚函数的虚函数,它本身的定义就是一个虚函数。相当于 override=virtual+重写,因此 virtual 关键字也就多余了。
1F
牛逼