首页 > 编程笔记 > C++笔记 阅读:65

C++ override和final的用法(非常详细,附带实例)

不像其他类似的编程语言,C++ 没有特定的语法来声明接口类型(基本上只在类中声明纯虚方法),并且在声明虚方法方面有一定的缺陷。

在 C++ 中,虚方法用关键字 virtual 声明。但是,在派生类中声明覆盖时,关键字 virtual 是可选的,这在处理大型类或层次结构时可能会导致混淆。你可能需要在整个层次结构中追溯到基类以确定函数是否是虚函数。另一方面,有时确保虚函数甚至派生类不能被重写或者进一步继承是必要的。

本节我们将学习使用 override 和 final 关键字声明虚函数和类。学习本文,读者要熟悉 C++ 中继承和多态,以及抽象类、纯虚说明符、虚方法和覆盖方法的概念。

C++ override和final的使用方式

为了确保在基类和派生类中正确地声明虚方法,同时提高可读性,请遵循以下原则:
1)在派生类中声明应该覆盖基类中的虚函数的虚函数时,建议使用 virtual 关键字。

2) 始终在虚函数声明或定义部分之后使用 override 特殊标识符:
class Base
{
    virtual void foo() = 0;
    virtual void bar() {}
    virtual void foobar() = 0;
};

void Base::foobar() {}

class Derived1 : public Base
{
    virtual void foo() override = 0;
    virtual void bar() override {}
    virtual void foobar() override {}
};

class Derived2 : public Derived1
{
    virtual void foo() override {}
};
声明符是函数类型中除去返回类型的部分。

为了保证函数不能被进一步覆盖或者类不能被进一步继承,请使用 final 特殊标识符:
1) 在虚函数声明或定义的声明符之后用 final 防止在派生类中对函数进行进一步覆盖:
class Derived2 : public Derived1
{
    virtual void foo() final {}
};

2) 在类声明中的类名后用 final 防止类被进一步继承:
class Derived4 final : public Derived1
{
    virtual void foo() override {}
};

C++ override和final的工作原理

override 关键字的用法很简单,在虚函数的声明或定义中,它可以保证函数确实覆盖了一个基类函数,否则,编译器会报错。

注意,override 和 final 关键字都是特殊标识符,仅在成员函数声明或定义中有意义。它们不是保留关键字,所以仍然可以在代码的其他任何地方用作自定义标识符。

使用 override 标识符有助于编译器检查虚方法是否覆盖另一个虚方法,如以下示例所示:
class Base
{
public:
    virtual void foo() {}
    virtual void bar() {}
};

class Derived1 : public Base
{
public:
    void foo() override {} // for readability use the virtual keyword

    virtual void bar(char const c) override {} // error, no Base::bar(char const)
};
如果不存在 override 标识符,则 Derived1 类的虚方法 bar(char const) 将不是覆盖方法,而是来自 Base 的 bar() 的重载。

另一个特殊标识符 final 用在成员函数声明或定义中,表示该函数是虚函数并且不能在派生类中被覆盖。如果派生类试图覆盖该虚函数,编译器会报错:
class Derived2 : public Derived1
{
    virtual void foo() final {}
};

class Derived3 : public Derived2
{
    virtual void foo() override {} // error
};

final 标识符也可以在类的声明中使用,表示该类不能被继承:
class Derived4 final : public Derived1
{
    virtual void foo() override {}
};

class Derived5 : public Derived4 // error
{
};

由于 override 和 final 在定义中使用时都具有特殊含义,并且实际上不是系统保留关键字,因此你仍然可以在 C++ 代码中的其他任何地方使用它们。这可以确保用 C++11 之前的版本编写的现有代码不会因使用它们作为标识符而损坏:
class foo
{
    int final = 0;
    void override() {}
};
尽管前面我建议在重写虚方法的声明中同时使用 virtual 和 override,但是 virtual 关键字是可选的,可以省略以缩短声明。override 标识符的存在应该是以表明该方法是虚方法,这是个人喜好问题,并不影响语义。

相关文章