C++ 中的 final 限定符
final 限定符 在 C++11 中引入,主要有两个用途 −
- 第一个用途是防止继承。当一个 class 被标记为 final 时,其他 class 不能继承它。
- 第二个用途是避免函数重写。当你将一个 virtual function 标记为 final 时,它就不能在派生类中被重写。
阅读本章以学习如何在 C++ 中使用 final 限定符。
将 final 限定符与 Class 一起使用
你可以将一个 class 标记为 final 来防止继承。标记为 final 后,你就不能再使用这个 class 进行继承。其他 class 将无法继承它。
将 final 限定符与 class 一起使用的语法如下 −
class MyClass final {
// class members
};
示例
以下示例演示了使用 final 和不使用 final 的 class 之间的区别 −
在这个示例中,我们在 Base class 上使用 final 限定符,而 Derived class 继承了基类。这将在输出中产生错误,如下所示 −
#include <iostream>
using namespace std;
class Base final // final class
{
public:
void display(){
cout << "Base class" << endl;
}
};
// Inheriting from final class
class Derived : public Base {
public:
void show(){
cout << "Derived class" << endl;
}
};
int main() {
Base b;
b.display();
return 0;
}
上述代码的输出如下 −
main.cpp:14:7: error: cannot derive from 'final' base 'Base' in derived
type 'Derived'
14 | class Derived : public Base
| ^~~~~~~
在这个示例中,我们从 Base class 中移除了 final 限定符,Derived class 继承了基类。它不会产生任何错误,并将正常工作 −
#include <iostream>
using namespace std;
class Base // removed final
{
public:
void display(){
cout << "Base class called" << endl;
}
};
// Inheriting from non-final class
class Derived : public Base {
public:
void show(){
cout << "Derived class called" << endl;
}
};
int main(){
Base b;
b.display();
return 0;
}
上述代码的输出如下 −
Base class called
使用 final 说明符与 Function
您可以使用 final 标记一个 function,以避免被覆盖该 function。标记一个 function 为 final 后,就无法再覆盖该 function。只有当 function 是virtual function时,才能将其标记为 final。
使用 final 说明符与 function 的语法如下所示 −
class Base {
public:
virtual void display() final {
// 实现
}
};
示例
下面的示例演示了使用 final 与不使用 final 时 function 的区别 −
在这个示例中,我们在 Mammal class 的 virtual function breathe() 上使用了 final 说明符。在 Dog class 中,我们尝试覆盖 breathe() function,这将在输出中产生错误。
#include <iostream>
using namespace std;
class Animal {
public:
virtual void makeSound(){
cout << "Animal sound" << endl;
}
virtual void breathe(){
cout << "Animal breathing" << endl;
}
};
class Mammal : public Animal {
public:
void makeSound() override{
cout << "Mammal sound" << endl;
}
// final function
void breathe() final override {
cout << "Mammal breathing" << endl;
}
};
class Dog : public Mammal{
public:
void makeSound() override {
cout << "Bark" << endl;
}
// 这将导致错误
void breathe() override {
cout << "Dog breathing" << endl;
}
};
int main(){
Dog dog;
dog.makeSound();
dog.breathe();
return 0;
}
上述代码的输出如下所示 −
main.cpp:42:10: error: virtual function 'virtual void Dog::breathe()' overriding
final function
42 | void breathe() override
| ^~~~~~~
main.cpp:27:10: note: overridden function is 'virtual void Mammal::breathe()'
27 | void breathe() final override
| ^~~~~~~
在这个示例中,我们从 Mammal class 的 breathe() function 中移除了 final 说明符。在 Dog class 中覆盖 breathe() function 后,它将正常工作,不会产生任何错误,并在输出中打印覆盖后的值。
#include <iostream>
using namespace std;
class Animal {
public:
virtual void makeSound(){
cout << "Animal sound" << endl;
}
virtual void breathe(){
cout << "Animal breathing" << endl;
}
};
class Mammal : public Animal{
public:
void makeSound() override {
cout << "Mammal sound" << endl;
}
// 移除了 final
void breathe() override {
cout << "Mammal breathing" << endl;
}
};
class Dog : public Mammal{
public:
void makeSound() override {
cout << "Bark" << endl;
}
// 现在这是安全的
void breathe() override {
cout << "Dog breathing" << endl;
}
};
int main(){
Dog dog;
dog.makeSound();
dog.breathe();
return 0;
}
上述代码的输出如下所示 −
Bark Dog breathing
结论
C++ 中的final 说明符有助于防止 class 的继承和 virtual function 的覆盖。在本章中,我们详细解释了 final 说明符如何与 class 和 virtual function 一起工作。