编程后端C++开发人员

C++中的‘override’关键字如何工作,为什么在重写虚函数时使用它?

用 Hintsage AI 助手通过面试

答案。

问题背景

虚函数自C++的开始就作为动态多态性的一种手段。然而,早期并没有语法机制来强制编译器检查派生类中虚函数重写的正确性。在C++11之后,‘override’关键字成为了额外编译器检查的工具。

问题

如果没有‘override’,编译器不能保证该函数确实重写了基类的方法。签名中的错误(例如,错误的类型或const)会导致在派生类中创建新函数(“遮蔽”),这会破坏多态性并使调试变得困难。

解决方案

在派生类中声明虚函数时使用‘override’允许编译器检查签名是否与父类的虚函数完全匹配,并且该函数确实重写了父类。如果不匹配,则编译过程会因错误而中断。

代码示例:

struct Base { virtual void foo() const {} }; struct Derived : Base { void foo() const override { /* 实现 */ } };

如果在‘Derived’中写成‘void foo()’而没有‘const override’,编译器将会报错。

主要特点:

  • 允许在编译阶段发现签名错误
  • 提高代码的可读性和可维护性
  • 团队标准中必须使用

可能的陷阱问题。

可以只保留带有‘override’关键字的虚函数,而没有关键字‘virtual’吗?

可以,‘override’隐含函数是虚拟的。将‘virtual’与‘override’一起指定是多余的,但没有禁止。

如果函数只因为const或引用限定符(例如,&或&&)的修饰符不同,是否可能会出错?

是的,签名中的任何差异,包括const/引用,会破坏重写。例如,‘void foo() override’不会重写‘void foo() const’,编译器会通过‘override’捕获这一点。

可以将‘override’应用于静态函数或构造函数吗?

不可以。‘override’仅适用于虚函数,不能应用于静态函数、构造函数、析构函数(如果它们不是虚拟的)。

常见错误和反模式

  • 重写时缺少‘override’
  • 隐式签名错误(例如,漏掉const)
  • 在静态函数或非虚函数上使用‘override’

生活中的例子

消极案例

在一个大型项目中,继承类的函数签名存在拼写错误:该函数实际上并没有重写,但开发者认为相反,多态性未按预期工作。

优点:

  • 不需要了解新标准

缺点:

  • 导致在运行时难以捕捉的错误

积极案例

在所有派生类中使用‘override’,测试在构建阶段捕获错误。

优点:

  • 重写错误立即显现
  • 提高了架构的质量和透明度

缺点:

  • 需要注意细节,关注签名并了解新标准