如何在重载虚拟方法声明中检测“虚拟”说明符?

假设你有这个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()的声明中缺less的' virtual '吗?

我不知道有任何gcc警告检测到这一点。

使用C ++ 11 覆盖功能。 编译器会输出警告或错误,如果不合适的话。

而不是依赖于容易出错的编码标准,让编译器这样做,检查你。

要回答下面的评论,你必须考虑到这两种情况:

  1. 如果具有相同签名和名称的基类方法不是虚拟的,则在方法上放置重写限定符将会输出错误。
  2. 如果在层次结构中不成为虚拟的,它也会输出一个错误。

所以这个代码:

 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 }; 

同意,这是乏味的,因为你必须复制每个子类的类的所有签名(不需要通过实现)。 所以,如果你想强制所有的孩子明确地覆盖所有的虚拟方法,他们从基类中“覆盖”,你需要“禁用”子类继承到基类,如下所示:

 #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);