不应该有虚拟功能隐藏的警告吗?

Shouldn't there be a warning for virtual function hiding?

本文关键字:警告 隐藏 虚拟 功能 不应该      更新时间:2023-10-16

在Scott Meyers的《有效C++:改进程序和设计的55种具体方法》(第3版)第9章中,有一节题为第53项:注意编译器警告Meyers说以下程序应该发出警告:

class B {
public:
  virtual void f() const;
};
class D: public B {
public:
  virtual void f();
};

并说:

D::f的想法是重新定义虚拟函数B::f,但是有一个错误:在B中,f是const成员函数,但在D中,它是未声明const。我认识的一个编译器这样说:

warning: D::f() hides virtual B::f()

太多缺乏经验的程序员对这条消息的回应是:对自己来说,"当然D::f隐藏了B::f——这就是它应该做的!"错了。这个编译器试图告诉你在B中声明的未在D中重新声明;相反,它被隐藏了完全(关于为什么会这样做的说明,请参见第33项)。忽略这个编译器警告几乎肯定会导致错误的程序行为,然后进行大量调试以发现编译器首先检测到。

但是我的编译器不会给出任何警告,即使使用-Wall也是如此。为什么我的编译器(GCC)不发出警告?

正如"chris"所指出的,如果您使用-Woverloaded-virtual,GCC将向您发出警告,尽管-Wall -Wextra没有启用这一功能。在任何情况下,你都不需要编译器来找到它,你可以使用C++11:

class B {
public:
  virtual void f() const;
};
class D: public B {
public:
  void f() override;
};

当您打算重写虚拟方法时,通过指定override,如果签名错误,编译器将给您一个错误(而不仅仅是警告)。


关于-Woverloaded-virtual,请注意,它警告的不仅仅是const:如果您定义了一个具有相同名称和完全不同参数的新方法,它也会发出警告。这类事情发生在真实的代码库中,可能是故意的,所以这可能就是为什么在任何粗粒度警告选项中都不能启用这一功能的原因。我想一个仅const的警告可能很好,但现在我们有了C++11,它似乎不那么相关了。