final
和 override
都是在特定场景使用有特殊含义的标识符(specifier / identifier ),并不是C++保留的关键字(not a reserved keyword )。
一、final
specifier (since C++11)
Specifies that a virtual function cannot be overridden in a derived class or that a class cannot be inherited from.
final
is an identifier with a special meaning when used in a member function declaration or class head. In other contexts it is not reserved and may be used to name objects and functions.
即:用于指定一个虚函数不能在派生类中被重写,或一个类不能被继承。
也就是 final
标识符作用的对象就是:类 或者 虚函数,且 final
是在成员函数定于或类头部时有特殊含义的标识符,但不是C++保留的关键字,可以被用于对象和方法的命名。
主要有 种用法:
- 用于虚函数的声明或定义
- 用于类的定义
1.1 用于虚函数的声明或定义
用途:限定这个虚函数不能被继承类重写(may not be overridden by derived classes)。且限定修饰的函数必须是虚函数。
位置:用于虚函数声明时,紧跟虚函数声明后边,且位于纯虚函数限定符(pure-specifier,即 = 0
)前边(如果有的话),如下。
struct Base {
virtual void foo();
};
struct A : Base {
void foo() final; // Base::foo is overridden and A::foo is the final override
// void bar() final; // Error: non-virtual function cannot be overridden or be final
};
struct B final : A { // struct B is final
// void foo() override; // Error: foo cannot be overridden as it's final in A
};
//struct C : B // Error: B is final
//{
//};
1.2 用于类的定义
用途:限定这个类不能被继承(cannot be derived from)。
位置:紧跟在类名后边,在 :
前边,如上 B
,及如下 A
:
class A final
{
};
class B : A {}; // Errpr: "B" : 无法从"A"继承,因为它已被声明为"final"
1.3 用于union
final
还可以被用作与 union
中,但是除了使用 is_final
输出类型以外,没有别的用处,因为 union
本身就不能被继承:
#include <iostream>
#include <type_traits> // is_final
using namespace std;
class A {};
class B final {};
union UA {};
union UB final {};
int main() {
cout << boolalpha
<< is_final<A>::value << '\n' // false
<< is_final<B>::value << '\n' // true
<< is_final<UA>::value << '\n' // false
<< is_final<UB>::value << '\n'; // true
}
二、override
specifier (since C++11)
Specifies that a virtual function overrides another virtual function.
override
is an identifier with a special meaning when used after member function declarators: it’s not a reserved keyword otherwise.
即:用于指定一个虚函数重写了另一个虚函数。override
是在成员函数后边时候有特殊含义的标识符,但是不是C++保留的关键字。
1.1 用于虚函数的声明或定义
用途:保证所修饰的函数是虚函数,且重写了基类的对应虚函数。也就是起到了辅助检查的作用,保证重写,且没有写错重写函数。且被 final
修饰的虚函数不能 override
。
位置:和 final
用于虚函数时一样。
struct A {
void foo() {}
virtual void func(int) {}
};
struct B : A {
virtual void func(int) override {} // OK
// virtual void func(double) override {} // Error: "B::func":包含重写说明符"override"的方法没有重写任何基类方法
// void foo() override {} // Error: 同上
};
三、“如何设计一个不能被继承的类”
问题其实是 “如何设计一个不能被继承的类,但不影响自身使用的类?”。
用C++11的话,如上所述,加一个 final
标识符就可以了,但是面试时候肯定问这个问题肯定会问如果不能用C++11,怎么实现?
解决方案为:使用友元、私有构造函数、虚继承等方式可以使一个类不能被继承。