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 intoBase
(and thus inherited byGrandKid
). 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 toGrandKid
because it's private inKid
.In the compiler's error message,
Base::Base
doesn't refer to the constructor, but to the class nameBase
injected intoBase
. Note that when the context in which it is used forces the name to be interpreted as a type, you can actually useBase::Base
legally, like in this valid, but vile code:[Live example]
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)