在了解C++11中的final/override之前,需要先了解一下C++中关于重载的概念。简单地说,一个类A中声明的虚函数fun在其派生类B中被再次定义,且B中的函数fun跟A中fun的原型一样(函数名、参数列表等一样),那么我们就称B重载了A的fun函数。对于任何B类型的变量,调用成员函数fun都是调用了B重载的版本。而如果同时有A的派生类C,却并没有重载A的fun函数,那么调用成员函数fun则会调用A中的版本。这在C++中构成多态。
其实上面这段话说的重载是通俗说法,上面所说的虚函数重载实际叫重写或覆盖,它们函数名、参数列表、返回值都相同。重载是在同一个作用域中的两个函数,它们函数名相同,参数列表不同,返回值可以相同可以不同。
假如类A和类B都是程序员1写的,类C由程序员2写。类B派生于类A,且基类B中有一个重写类A的fun函数,而程序员2并不知道,那么当他在写派生类C时也写了一个fun函数(派生类重写不用加virtual),那么继承于基类B的虚函数表(函数指针数组)就会修改关于fun函数的地址从原来B::fun变为C::fun,这就构成了重写。
程序员1想让后面所有的程序员都使用他写的类B中的fun函数,形成统一的标准(比如统一打印函数格式)不希望B的派生类的fun函数被重写。用一个生动的说法就是,到了类B这,fun函数说我累了不想再漂泊了,就到这吧。给fun函数后面加上final关键字,类C就不能重写或覆盖继承于类B的fun函数了。
所以final关键字的作用就是使派生类不可覆盖final修饰的的虚函数。当派生类对基类的加了final的虚函数进行了重载则会造成编译错误。从接口派生的角度而言,final可以在派生过程中任意的阻止一个接口的可重载性,这就给面向对象的程序员带来了更大的控制力。
基类虚函数加virtual关键字但是派生类函数重写时却并不用加vitual,这是编译器做的优化。但是这样却带来了一些阅读上的困难,如果继承结构较长,派生类的编写者会遇到信息分散、难以阅读的问题。在C++11中为了帮助程序员写继承结构复杂的类型,引入了虚函数描述符override,如果派生类在虚函数声明时使用了override描述符,那么该函数必须重写基类中的同名函数,否则代码无法通过编译。