override和final说明符
分清重写,重载和隐藏
重载(overload), 它通常是指在同一个类中有两个或两个以上的函数,它们的函数名相同,但是函数签名不同,也就是说有不同的形参。
重写(ovrride)的意思更接近覆盖, 在C++中是指派生类覆盖了基类的虚函数
隐藏(overwrite)是指基类成员函数,无论它是是否是为虚函数,当派生类出现同名函数时,如果派生类函数签名不同于基函数,则基类函数会被隐藏。如果派生类函数签名与基函数相同,则需要确定基类函数是否为虚函数,如果时虚函数这里的概念就是重写,否则基类函数也会被隐藏。
override 说明符
- 检查是否符合重写规则,让编译器来检查我们又没有正确覆写父类的虚函数。因此,任何子类覆写虚函数后导致函数签名的变化,都会导致编译器报错。
-如果你一直使用override,他还会给你带来一个意想不到的收获:在C++11之前,关于子类覆写父类虚函数后,子类的虚函数还要不要加virtual关键字,还是个值得争论的问题。人们一开始之所以想在子类的覆写函数上也加上virtual,就是为了提醒读代码的人这是个覆写的虚函数。但是在有了override之后,这个关键字本身就起了这个作用,之前的做法也就不是必须的了。所以建议的做法是,在最顶层的虚函数上加上virtual关键字后,其余的子类覆写后就不再加virtual了,但是要统一加上override
1 | class Base{ |
final说明符
- 阻止派生类去继承基类虚函数
1 | class Base{ |
- 阻止类被作为基类
1 | class Base final { |
如何更新你的代码
如果你的代码已经非常冗长并且到处都是覆写的虚函数,这个时候你想用final和override来更新你的代码库,我会给你以下建议:
- 在处理final时应该慎之又慎,需要case by case地处理。
- 至于override,无论哪里用到了覆写,直接加上去就完事了,只会有益处而不会有害,不过看清楚你的本意到底是不是覆写哈。尤其是你加上override后编译器报错的,一定要先检查你的本意到底是不是覆写,确定你真的犯了错误后,再去修改源代码。
- 加上override后,我建议你把子类的virtual关键字去掉,并且以后都遵循上边提到的规范:只有顶层的虚函数加上virtual,其余子类在覆写时全部用override来标记。
- 当你看到一个函数标记了virtual时,弄清楚它是不是顶层虚函数其实是一件非常困难的事情,这个时候我建议你多用用你的编译器,当你使用override报错时,也有可能它确实就是顶层virtual函数了。
结论
override和final都能帮助我们改善虚函数相关的安全性,使用final需要更多的权衡但是override就尽管大胆地用吧。