假设您有这个 Base
类:
class Base
{
public:
virtual void foo();
};
您可以在派生自 Base
的类中覆盖 foo()
:
class Derived : public Base
{
public:
virtual void foo();
};
但是,如果您在 Derived::foo()
的声明中“忘记”'virtual
':
class Derived : public Base
{
public:
void foo();
};
你得到完全相同的语义:Derived::foo()
是虚拟的,尽管没有明确声明。
现在,假设您的编码标准规定在这种情况下应明确提及“virtual
”。
您是否知道一种简单的方法(在 Linux + gcc 环境中)来检测 Derived::foo()
声明中缺少的“virtual
”?
我不知道有任何 gcc 警告检测到这一点。
最佳答案
使用 C++11 override特征。 如果不合适,编译器将输出警告或错误。
与其依赖容易出错的编码标准,不如让编译器为您进行检查。
要回答下面的评论,您必须考虑这两种情况:
- 如果具有相同签名和名称的基类方法不是虚拟的,则在方法上放置一个override 限定符将输出错误。
- 如果它在层次结构中没有变成虚拟的,它也会输出一个错误。
所以这段代码:
struct A
{
void foo();
virtual int bar();
};
struct B : A
{
virtual void foo(); // If you add override here, it errors, if you forget "virtual" it errors too, later in C
int bar() override;
};
// Write this for each subclass:
struct C : B
{
void foo() override; // Fails if B does not have "virtual" keyword
};
同意,这很乏味,因为您必须为每个子类复制类的所有签名(不需要通过实现)。所以,如果你想强制你所有的 child 明确地覆盖他们从基类“覆盖”的所有虚方法,你需要“禁用”子类对基类的继承,就像这样:
#ifndef CheckVirtual
#define WITH_BASE(X) : public X
#else
#define WITH_BASE(X)
#endif
struct A
{
virtual int bar();
virtual void baz();
};
//==== \/ This is the hostile code to test \/ ========
struct B WITH_BASE(A)
{
virtual int bar();
void baz();
};
//==== End of hostile code ====
//==== \/ Start of enforcer code, you must have one enforcer header per base class to check for
// Notice that Enforcer must reproduce interface of A
struct Enforcer : B
{
int bar() override;
void baz() override; // Error here if CheckVirtual is defined, since B::baz is not virtual.
};
// Or better, some sugar, if you have plenty of child of A, with some macro magic:
template <typename T>
struct VirtualEnforcer_ : T
{
#include "Your_A_Interface_Here"
};
#define EnforceVirtual(X) VirtualEnforcer_<X> assertVirtual ## X ()
EnforceVirtual(B);
EnforceVirtual(AnotherChildOfA);
关于c++ - 如何检测重写虚方法声明中的 "missing" 'virtual' 说明符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26058232/