Why does class D
compile, but class C
does not?
class A { public: A(int) {} }; template <class T> class B : private T // Note: private base class { public: using T::T; }; class C : public B<A> { public: C() : B<A>(123) {} // Error: 'class A A::A' is inaccessible }; // within this context using BA = B<A>; class D : public BA { public: D() : BA(123) {} // OK };
I tested with GCC, Clang and Visual C++, and they are all the same. Changing class B : private T
to public T
solves the problem. But why? (Note that the using T::T
is public
.)
Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.
To inherit only selected ones you need to write the individual constructors manually and call the base constructor as needed from them. Historically constructors could not be inherited in the C++03 standard. You needed to inherit them manually one by one by calling base implementation on your own.
Inheriting from a template classIt is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.
Constructors are not inherited. The superclass constructor can be called from the first line of a subclass constructor by using the keyword super and passing appropriate parameters to set the private instance variables of the superclass.
Class A
contains the injected-class-name A
within its scope (that is, A::A
refers to class A
unless it happens to refer to the constructor).
Class B
inherits this, so the name A
within the scope of B
refers to the injected-class-name A
in scope of A
. However, since A
is a private base class of B
, all names in scope of A
are private within B
.
Class C
again inherits this, but it cannot access this A
, since it is private within B
. Hence the error. Note that the error is actually with using the name A
in the construct B<A>
.
Class BA
doesn't have this problem, since the definition B<A>
is not in the scope of any class, so the name A
refers to the global name A
and not to any injected-class-name. And of course, the name BA
is public.
You can easily solve this by qualifying the name A
in C
:
class C : public B<A> { public: C() : B<::A>( 123 ) {} };
Note that constructor inheritance has no effect there. The problem is with access to the class name A
(injected in A
and inherited in B
and C
), not with access to the constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With