在C++中,
final
关键字用于防止类被继承或者防止虚函数被覆盖。具体来说,
final
可以用于两个场景:
- 用于类:禁止该类被继承。
- 用于虚函数:禁止该虚函数在派生类中被重写。
接下来,我们详细说明这两个用法,并给出代码示例及解释代码和输出结果。
用法一:用于类
当 final
关键字用于类时,这个类不能被其他类继承。当设计一个类时,开发者有时会希望这个类不被继承,防止继承带来的复杂性和潜在错误。例如,一个类的设计可能非常具体和封闭,不适合被扩展.
示例代码
#include <iostream>
class Base final
{
public:
void display() const
{
std::cout << "Base display" << std::endl;
}
};
// 以下代码会导致编译错误
// class Derived : public Base
//{
// };
int main()
{
Base b;
b.display();
return 0;
}
代码解释
在这个例子中,Base
类被标记为 final
,因此不能被继承。如果尝试继承 Base
类(如注释掉的 Derived
类),编译器将报错。
输出结果
由于 Derived
类被注释掉了,代码可以正常编译并运行。输出将会是:
Base display
用法二:用于虚函数
当 final
关键字用于虚函数时,这个虚函数在派生类中不能被重写。在某些情况下,基类中的虚函数的行为已经完全确定,不希望派生类对其进行修改。
示例代码
#include <iostream>
class Base
{
public:
virtual void display() const
{
std::cout << "Base display" << std::endl;
}
};
class Derived : public Base
{
public:
void display() const final
{
std::cout << "Derived display" << std::endl;
}
};
// 以下代码会导致编译错误
// class FurtherDerived : public Derived
//{
// public:
// void display() const override
// {
// std::cout << "FurtherDerived display" << std::endl;
// }
// };
int main()
{
Base* b = new Derived();
b->display();
delete b;
return 0;
}
代码解释
在这个例子中,Derived
类中的 display
函数被标记为 final
,因此 FurtherDerived
类不能重写它。如果尝试重写(如注释掉的 FurtherDerived
类),编译器将报错。
输出结果
由于 FurtherDerived
类被注释掉了,代码可以正常编译并运行。输出将会是:
Derived display
总结
final
关键字在C++中主要有两个作用:
- 防止类被继承:当一个类被标记为
final
时,任何尝试继承这个类的操作都会导致编译错误。 - 防止虚函数被重写:当一个虚函数被标记为
final
时,任何尝试在派生类中重写这个函数的操作都会导致编译错误。 - 提高性能:虽然现代C++编译器非常智能,能够进行许多优化,但明确标记某些类或函数为 final 可以帮助编译器进行额外的优化。例如,编译器知道某个类不会有派生类,或者某个虚函数不会被重写,可以省略一些虚函数表(vtable)的检查,进而提高性能。
- 提高代码的可读性和可维护性:明确地使用 final 关键字能够传达设计意图,提醒其他开发人员这个类或函数不应该被继承或重写。这样可以减少误用,提高代码的可读性和可维护性。
通过使用 final
关键字,程序员可以更好地控制类的继承和虚函数的重写,确保类设计的完整性和预期行为。