How do I detect a "missing" "virtual" qualifier in an overridden virtual method declaration?

Let's assume you have this class Base

:

class Base
{
public:
    virtual void foo();
};

      

You can override foo()

in a class derived from Base

:

class Derived : public Base
{
public:
    virtual void foo();
};

      

If, however, you "forgot" " virtual

" in the declaration Derived::foo()

:

class Derived : public Base
{
public:
    void foo();
};

      

you get exactly the same semantics: Derived::foo()

is virtual, although not explicitly declared.

Now, suppose your coding standard dictates that " virtual

" must be specified explicitly in such cases.

Do you know an easy way (in Linux + gcc environment) to find a missing " virtual

" in a declaration Derived::foo()

?

I am not aware of any gcc warning that detects this.

+3


source to share


1 answer


Use the C ++ 11 override feature . The compiler will issue a warning or error if it doesn't fit.

Instead of relying on the error coding standard, let the compiler do this check for you.

To answer the comments below, you must consider both cases:

  • Putting an overriding qualifier on a method will throw an error if a base class method with the same signature and name is not virtual.
  • It will also throw an error if it doesn't become virtual in the hierarchy.


So this code:

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

      

Agreed, this is tedious as you have to replicate all class signatures for each subclass (no implementation needed). So, if you want all your children to forcibly override all virtual methods, they "override" from the base class, you need to "disable" inheritance of the child class from the base class, for example:

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

      

-2


source







All Articles