不像其他类似的编程语言,C++没有特定的语法来声明接口类型(基本上只在类中声明纯虚方法),并且在声明虚方法方面有一定的缺陷。在C++中,虚方法用关键字virtual声明。但是,在派生类中声明覆盖时,关键字virtual是可选的,这在处理大型类或层次结构时可能会导致混淆。你可能需要在整个层次结构中追溯到基类以确定函数是否是虚函数。另一方面,有时确保虚函数甚至派生类不能被重写或者进一步继承是必要的。在本节中,我们将学习使用override和final关键字声明虚函数和类。
你应该熟悉C++中继承和多态,以及抽象类、纯虚说明符、虚方法和覆盖方法的概念。
为了确保在基类和派生类中正确地声明虚方法,同时提高可读性,请遵循以下原则:
❍ 在派生类中声明应该覆盖基类中的虚函数的虚函数时,建议使用virtual关键字。
❍ 始终在虚函数声明或定义部分之后使用override特殊标识符:
声明符是函数类型中除去返回类型的部分。
为了保证函数不能被进一步覆盖或者类不能被进一步继承,请使用final特殊标识符:
❍ 在虚函数声明或定义的声明符之后用final防止在派生类中对函数进行进一步覆盖:
❍ 在类声明中的类名后用final防止类被进一步继承:
override关键字的用法很简单:在虚函数的声明或定义中,它可以保证函数确实覆盖了一个基类函数,否则,编译器会报错。
注意,override和final关键字都是特殊标识符,仅在成员函数声明或定义中有意义。它们不是保留关键字,所以仍然可以在代码的其他任何地方用作自定义标识符 。
使用override标识符有助于编译器检查虚方法是否覆盖另一个虚方法,如以下示例所示:
如果不存在override标识符,则Derived1类的虚方法bar(char const)将不是覆盖方法,而是来自Base的bar()的重载。
另一个特殊标识符final用在成员函数声明或定义中,表示该函数是虚函数并且不能在派生类中被覆盖。如果派生类试图覆盖该虚函数,编译器会报错:
final标识符也可以在类的声明中使用,表示该类不能被继承:
由于override和final在定义中使用时都具有特殊含义,并且实际上不是系统保留关键字,因此你仍然可以在C++代码中的其他任何地方使用它们。这可以确保用C++11之前的版本编写的现有代码不会因使用它们作为标识符而损坏:
尽管前面我建议在重写虚方法的声明中同时使用virtual和override,但是virtual关键字是可选的,可以省略以缩短声明。override标识符的存在应该足以表明该方法是虚方法,这是个人喜好问题,并不影响语义。
❍ 阅读10.6节,以了解CRTP模式如何帮助在编译时实现多态。