override和final标识符
override
和final
是C++引入的新的标识符
。注意是标识符不是关键字。
标识符和关键字的区别
关键字(KEYWORD)
:也称保留字。它们为语言所用,不可用于重定义或重载。
标识符(IDENTIFIERS)
:一个标识符是一个由数字,下划线,小写和大写拉丁字母,和大多数 Unicode 字符组成的任意长度的序列。在声明中,可以用标识符来命名对象、引用、函数、枚举项、类型、类成员、命名空间、模板、模板特化、形参包、goto 标号,以及其他实体。
override和final标识符
: 拥有特殊含义的标识符,可用作对象或函数的名字,但在某些语境拥有特殊含义。
也就是说,override和final也是标识符,也可以作为对象名,或函数名。只是在特殊的语境中有特殊的含义,和作为对象名和函数名是不冲突的。但关键字不可以这样。
例子:
#include <iostream>
class A {
public:
virtual void show() {
std::cout << "A::show(), override = " << override << std::endl;
}
private:
int override = 1;
};
class B : public A {
public:
virtual void show() override {
std::cout << "B::show(), override = " << override << std::endl;
}
private:
int override = 2;
};
int main() {
A* ptr1 = new A();
A* ptr2 = new B();
ptr1->show();
ptr2->show();
}
输出
A::show(), override = 1
B::show(), override = 2
作为函数名也是可以的,但不能同时命名override为对象名和函数名,就不举例说明了。
因为是C++11才引入的,编译时要指定C++11,否则编译有告警提示
warning: override controls (override/final) only available with -std=c++11 or -std=gnu++11 [enabled by default]
override标识符
为什么要引入override标识符? C++11以前没有时,是什么样?
还是刚才的例子:
#include <iostream>
class A {
public:
virtual void show() {
std::cout << "A::show(), override = " << override << std::endl;
}
private:
int override = 1;
};
class B : public A {
public:
virtual void show(int a) { //变化行
std::cout << "B::show(), override = " << override << std::endl;
}
private:
int override = 2;
};
int main() {
A* ptr1 = new A();
A* ptr2 = new B();
ptr1->show();
ptr2->show();
}
输出
A::show(), override = 1
A::show(), override = 1
因为Class B的本意是重写Class A的show方法。 由于参数不一致,导致是新增了一个虚函数。由于没有重写基类方法,无法多态调用到派生类的方法。
重写函数必须有相同的类型,名称和参数列表。需要人为去保证,往往容易出现错误,导致和预期不一致。
当需要重写基类方法时,使用override关键字,这样可以将重写的检查工作交给编译器会去做。
例子中增加关键字override:
...
virtual void show(int a) override {
...
编译将报错:
error: ‘virtual void B::show(int)’ marked override, but does not override
所有override标识符的作用是: 将重写的检查交给编译器,减少人为出错的可能。
在重写基类方法时,加上override标识符是正确的选择。
final标识符
final 是在成员函数声明或类头部中使用时有特殊含义的标识符。其他语境中它未被保留,而且可用于命名对象或函数。
final可以用于
- 类声明: 指定某个类不能被子类继承。
- 函数声明: 指定某个虚函数不能在子类中被覆盖。
类声明
class A final {
public:
virtual void show() {
std::cout << "A::show(), override = " << override << std::endl;
}
private:
int override = 1;
};
如果Class B继承Class A,编译将报错
error: cannot derive from ‘final’ base ‘A’ in derived type ‘B’
函数声明
virtual void show() final {
std::cout << "A::show(), override = " << override << std::endl;
}
Class B重写show方法时,也会报错。
注意:
- final不能用于非虚方法。除非这个非虚方法是重写基类的方法。
- 派生类重写基类的虚方法也可以指定为final,表示这个方法不能再其被派生类重写。
参考:
https://zh.cppreference.com/w/cpp/keyword
https://www.bogotobogo.com/cplusplus/C11/C11_override_final.php
https://zh.cppreference.com/w/cpp/language/override
https://zh.cppreference.com/w/cpp/language/fin