Compiler bug?

24 Apr 2012

I have a base class with one pure virtual function defined at the permission level protected.

A second class inherits from the first and implements the protected pure virtual function. This second class has it's own public pure virtual function with the same name but different param's.

A third class inherits from the second and implements the public pure virtual function.

The compiler warns that the implemented public function is hidden by the protected function in the first class.

E.G

class ClassA { protected: virtual void DoSomething() = 0; };

class ClassB : ClassA { protected: virtual void DoSomething();

public: virtual void DoSomething(int aValue) = 0; };

void ClassB::DoSomething() { Does something. }

class ClassC : ClassB { public: virtual void DoSomething(int aValue); };

void ClassB::DoSomething(int aValue) { Does something. }

The warning I get is "function "ClassA::DoSomething()" is hidden by "ClassC::DoSomething" virtual function override intended?" in file "/main.cpp", Line: 31, Col: 15

This is wrong as, C++ name mangling treats these functions as different functions because of their different parameters.

25 Apr 2012

Hi Richard,

Looks like you are in quite deep in to C++/virtual inheritance/overloading, which is always going to be fun!

As much as it may seem like you should get your expected behaviour, I think the compiler is actually fine. Take a read of this and you might get more insight in to this corner case of C++:

The section is called "What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?", and the first line of the answer is "It means you're going to die.", so I think that just about sums it up :)

Hope that helps!

Simon

25 Apr 2012

MS compiler and GCC are fine with this code but I don't know how comformant they are. I'll have to drag out my "Inside the C++ Object Model" book. :) My gut feeling is that the compiler is using a short cut and generating a false warning. But then it could be a correct warning from a comformant compiler.

25 Apr 2012

I don't think warnings (diagnostic messages) are defined explicitly by the standard. They are part of the undefined behaviour that is allowed to be implemented however the implementor sees fit.

I took your above example and converted it into this code:

class ClassA 
{ 
protected: 
    virtual void DoSomething() = 0; 
};

class ClassB : ClassA 
{ 
protected: 
    virtual void DoSomething() { }

public: 
    virtual void DoSomething(int aValue) = 0; 
};

class ClassC : ClassB 
{ 
public: 
    virtual void DoSomething(int aValue) { (void)aValue; } 
};

int main(int argc, char** argv)
{
    ClassC objectC;
    
    objectC.DoSomething(1);
    
    return 0;
}

This code compiles with no warnings when I use the LLVM compiler on OS X.

However if I switch the main function to be this

int main(int argc, char** argv)
{
    ClassC objectC;
    
    objectC.DoSomething();
    
    return 0;
}

then the code fails to compile with the following error:

main.cpp:27:25: error: too few arguments to function call, expected 1, have 0
    objectC.DoSomething();
    ~~~~~~~~~~~~~~~~~~~ ^
main.cpp:19:5: note: 'DoSomething' declared here
    virtual void DoSomething(int aValue) { (void)aValue; } 
    ^

This would make it appear that the warning you get with the online compiler is correct. The version with no parameters has been hidden.

If you happen to have the C++ standard, you can look at section 13.2 Declaration matching. It shows an example that is almost exactly the same as yours and indicates that the derived version hides the base version. The issue is that overloading only applies when the functions are at the same scope and the base class is not at the same scope as the derived class.