假设你有这个Base
类:
class Base
{
public:
virtual void foo();
};
您可以覆盖从foo()
派生的类中的Base
:
class Derived : public Base
{
public:
virtual void foo();
};
但是,如果您在virtual
声明中“忘记”“Derived::foo()
”:
class Derived : public Base
{
public:
void foo();
};
你得到完全相同的语义:Derived::foo()
是虚拟的,虽然没有明确声明。
现在,假设您的编码标准规定在这种情况下应明确提及“virtual
”。
您是否知道在virtual
声明中检测丢失的“Derived::foo()
”的简单方法(在Linux + gcc环境中)?
我不知道有任何gcc警告可以检测到这一点。
答案 0 :(得分:-2)
使用C ++ 11 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
};
同意,这很乏味,因为你必须为每个子类复制所有类的签名(不需要通过实现)。因此,如果您希望强制所有子项明确覆盖它们从基类“覆盖”的所有虚方法,则需要“禁用”子类继承到基类,如下所示:
#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);