Consider:
#include <iostream>
using namespace std;
struct A {
virtual void f() { cout << "A::f" << endl; }
virtual void f() const { cout << "A::f const" << endl; }
};
struct B : public A {};
struct C : public A {
virtual void f() { cout << "C::f" << endl; }
};
int main()
{
const B b;
b.f(); // prints "A::f const"
const C c;
c.f();
// Compile-time error: passing ‘const C’ as ‘this’ argument of
// ‘virtual void C::f()’ discards qualifiers
}
(I'm using GCC.)
So it seems that the const version of f() gets hidden in C. This makes a lot of sense to me, but is it mandated by the standard?
I will (once more) link this great article :
So yes, the
const
version off
is hidden, and that's perfectly normal. As pointed out by Simone, you can use ausing
statement to bringA::f
inC
scope.Insert
using B::f;
C++ Standard 2003. 13.2 p.1:
Thus
C::f
hides allA::f
.Yes, it is. You may write:
to make your code compile:
For more infos, you can refer to the 2010 C++ draft document's (which you can find here) chapter 10.2.(3-4).
It is not the virtuality or const-ness (or lack thereof) that hides the base member, any derived method hides a base method of the same name. This was done to ameliorate the fragile base class problem.
Imagine your code was working (possibly for years) as below, with non-relevant parts removed:
Then you need to modify Base to include a method that does something completely different, but, for some reason, you want to name it 'f':
Without this rule, every use of a Derived calling f needs to be manually evaluated — and if Base is in a library given to other people, you may not even have access to those other uses! It gets worse in the face of user-defined (implicit) conversions.
Instead, it was decided to require derived classes to explicitly state they want to import given names from Base with a using declaration. This rule can be surprising and I'm not sure it's a net benefit to the language today, but they didn't ask me — at the time, I could probably only have answered them with two-syllable words, anyway. :)