clang emits a warning when compiling the following code:
struct Base
{
virtual void * get(char* e);
// virtual void * get(char* e, int index);
};
struct Derived: public Base {
virtual void * get(char* e, int index);
};
The warning is:
warning: 'Derived::get' hides overloaded virtual function [-Woverloaded-virtual]
(the said warning needs to be enabled of course).
I don't understand why. Note that uncommenting the same declaration in Base shuts the warning up. My understanding is that since the two get() functions have different signatures, there can be no hiding.
Is clang right? Why?
Note this is on MacOS X, running a recent version of Xcode.
clang --version
Apple LLVM version 5.0 (clang-500.1.74) (based on LLVM 3.3svn)
Update: same behavior with Xcode 4.6.3.
This warning is there to prevent accidental hiding of overloads when overriding is intended. Consider a slightly different example:
struct chart; // let's pretend this exists
struct Base
{
virtual void* get(char* e);
};
struct Derived: public Base {
virtual void* get(chart* e); // typo, we wanted to override the same function
};
As it is a warning, it doesn't necessarily mean it is a mistake, but it might indicate one. Usually such warnings have a means of shutting them off by being more explicit and letting the compiler know you did intend what you wrote. I believe in this case you can do the following:
struct Derived: public Base {
using Base::get; // tell the compiler we want both the get from Base and ours
virtual void * get(char* e, int index);
};
R. Martinho Fernandes solution's is perfectly valid if you actually want to bring the get()
method taking a single char* argument into Derived
scope.
Actually, in the snippet you provided, there is no need for virtual methods (since Base and Derived do not share any method with the same signature).
Assuming there is actually a need for polymorphism, the hiding behavior could nonetheless be what is intended.
In this case, it is possible to locally disable Clang's warning, with the following pragma :
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
// Member declaration raising the warning.
#pragma clang diagnostic pop
Another way of disabling the warning keeping the struct public interface intact would be:
struct Derived: public Base
{
virtual void * get(char* e, int index);
private:
using Base::get;
};
This disallows a consumer of Derived
to call Derived::get(char* e)
while silencing the warning:
Derived der;
der.get("", 0); //Allowed
der.get(""); //Compilation error
Warning means, that there will be no
void * get(char* e)
function in the scope of Derived class, cause it hidden by another method with same name.
Compiler won't search for function in base classes if derived class has at least one method with specified name, even if it has another arguments.
This sample code won't compile:
class A
{
public:
virtual void Foo() {}
};
class B : public A
{
public:
virtual void Foo(int a) {}
};
int main()
{
B b;
b.Foo();
return 0;
}