在继承关系中,派生类如果意图覆盖基类的虚函数,但是由于拼写错误或者参数类型不匹配等原因导致并没有真正覆盖成功,但直到运行时才能发现程序的行为未满足预期。如何将这一问题更早的发现呢?
有时为确保程序的稳定性和安全性,希望禁止派生类重写虚函数,甚至禁止类被继承,可是如何在程序层面做出限制而非仅仅通过说明文档告知下游开发者呢。
override
先看代码:
class Base {
public:
virtual void foo(int)
{}
};
class Derived1 : public Base
{
public:
void foo(float)//参数类型不匹配
{}
};
class Derived2 : public Base
{
public:
void foo_(int) //函数名拼写错误
{}
};
如上的子类Derived1和Derived2都继承自父类Base,两个子类中的方法foo和foo_均想重写父类中的方法foo,但是由于疏忽两者均未能实现预期效果,并且未能满足预期效果这一事实只有在运行期才能发现。
基于此,C+++提出了关键字override,override关键字用于显式指明派生类中的虚函数要覆盖基类中的虚函数,如果函数签名不匹配,则编译器会产生错误提示。在如上的两个子类中为函数foo和foo_注明override属性后,在编译器即可告知程序员,存在错误。
如下图所示
因此,一旦想到重写父类的虚函数时,请大胆的将函数标注为override。
final
final 关键字用于修饰类或者虚函数,表示该类不能被继承,或者该虚函数不能被派生类覆盖。
class Base {
public:
virtual void foo() final; // 使用 final 修饰的虚函数不能被派生类覆盖
};
class Derived : public Base {
public:
void foo(); // 编译错误:Derived::foo 尝试覆盖 final 的函数 Base::foo
};
class FinalClass final {
// 无法继承 FinalClass 类
};
class DerivedFinal:public FinalClass
{
}
如上代码会出现错误
编译器会告知,无法重写final函数,也无法继承自final基类。
应用场景
总结
本文提出了日常开发中存在的两个问题——重写虚函数、禁止重写虚函数和禁止类被继承,为了尽早的发现虚函数重写问题可以使用关键字override,为显性的在代码层面做出禁止重写禁止被继承的限制,使用关键字override和final。