Reputation: 6452
The GCC manual contains the following explanation of the warning option -Woverloaded-virtual:
Warn when a function declaration hides virtual functions from a base class. For example, in:
struct A {
virtual void f();
};
struct B: public A {
void f(int);
};
The A
class version of f
is hidden in B
, and code like:
B* b;
b->f();
Fails to compile.
What is the problem with this code? If it fails to compile, why is it a warning and not an error message? What is the canonical way to fix this and why?
Upvotes: 0
Views: 129
Reputation: 169038
Introducing a name that is inherited from an ancestor type causes that name to be hidden in the derived type. This is why b->f();
does not compile.
The warning comes from the declaration of B::f
. The compiler is telling you that this new declaration does not overload or override the function inherited from A
. It hides it within B
's scope. Sometimes you might want this, and there is nothing technically wrong with it, which is why it is not an error. However, because A::f
is hidden in B
, you can't invoke it (statically) on a B
value/reference.
Note that this has nothing to do with the inherited member function being virtual (though you would not receive the warning about the declaration of B::f
if A::f
were not virtual, nevertheless both will fail to compile b->f()
for the same reason). Perhaps more interesting, note that a type deriving B
can override A::f
even though it is not visible in B
.
To have both (an overloaded f()
in B
) you can explicitly bring the name f
from A
into B
:
struct B: public A {
using A::f;
void f(int);
};
Now both f()
overloads are visible within B
. Note that void f()
is still virtual, but void f(int)
was not declared virtual and so it isn't.
Another (ugly) workaround is to upcast the B
pointer/reference to an A
pointer/reference:
B *b = new B;
static_cast<A*>(b)->f();
Or, with a value instead of a pointer:
B b;
static_cast<A&>(b).f();
This uses the virtual function through the A
type, where it is not hidden.
Upvotes: 2