I have a simple question regarding inheriting from a class which privately inheriting of a base class, i.e. we have
class Base {};
class Heir: private Base {};
class HeirsHeir : public Heir {};
In understand that HeirsHeir
cannot access anything of 'its' Base
. In particular, it cannot have a method returning a Base &
reference to itself. But why can't it return a reference to another Base object? So why does the following code not compile:
class Base {};
class Kid : private Base {};
Base instance;
class Grandkid : public Kid
{
const Base &GetInstance () const
{ return instance; }
};
At least my compiler (MinGW 5.3, i.e. gcc for Windows) gives
error 'class Base Base::Base' is inaccessible at {};
error: within this context const Base &getInstance () const
For my understanding this doesn't make sense as I do not call the constructor of Base at this point, but return a reference (to a Base instance).
Note that the error can be fixed by using
const ::Base &GetInstance () const
{ return instance; }
which is surely linked to C++03 §11.2/3 (see [C++ private inheritance and static members/types)
Note: A member of a private base class might be inaccessible as an inherited member name, but accessible directly.
But I do not understand why this is necessary. Can somebody explain it?
The name lookup finds the injected-class-name Base
which is injected into Base
(and thus inherited by GrandKid
). This is correct, since the injected-class-name is in a closer scope than the namespace-scope name of the class. However, this injected-class-name is not accessible to GrandKid
because it's private in Kid
.
In the compiler's error message, Base::Base
doesn't refer to the constructor, but to the class name Base
injected into Base
. Note that when the context in which it is used forces the name to be interpreted as a type, you can actually use Base::Base
legally, like in this valid, but vile code:
class Foo {};
std::vector<Foo::Foo::Foo::Foo> v;
However, when the context in which Base::Base
is used would allow referring to a function, it is taken to resolve to the constructor and not to the class name (C++11 [class.qual] 3.4.3.1/2)