Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inherited constructors, default constructor and visibility

As stated by [namespace.udecl]/18:

[...] A using-declaration that names a constructor does not create a synonym; instead, the additional constructors are accessible if they would be accessible when used to construct an object of the corresponding base class, and the accessibility of the using-declaration is ignored. [...]

Because of that, the following code does not compile:

class B { protected: B(int) { } };
class D: B { using B::B; };
int main () { D d{0}; }

It returns an error that is more or less the same with all the major compilers:

declared protected here

On the other side, the following code compiles:

class B { protected: B() { } };
class D: B { using B::B; };
int main () { D d{}; }

Shouldn't it fail to compile instead for the same reasons that lead to an error in the previous example?
What does it allow it to compile?

like image 682
skypjack Avatar asked Oct 17 '16 08:10

skypjack


People also ask

Are default constructors inherited?

The default constructor in the Person class is not inherited by Employee and therefore a default constructor must be provided in Employee, either automatically by the compiler or coded by the developer. Note that the compiler will also generate a call to the base class default constructor.

Are default constructors private or public?

By default, constructors are defined in public section of class.

Can you inherit constructors?

Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.

Can default constructor be protected?

Typically, constructors have public accessibility so that code outside the class definition or inheritance hierarchy can create objects of the class. But you can also declare a constructor as protected or private . Constructors may be declared as inline , explicit , friend , or constexpr .


2 Answers

class B { protected: B() { } };
class D: B { using B::B; };
int main () { D d{}; }

D has no user-defined constructor in this case, so the compiler generates one (public) for you that calls B::B (but not because of the using, that has no effect in this case), that compiler-generated constructor is then called by main.

class B { protected: B(int) { } };
class D: B { using B::B; };
int main () { D d{0}; }

Even though D has no user-defined constructor here, the compiler-generated one is implicitly deleted because B only has a constructor that takes an int. D does also have a constructor that takes an int (using did that) but this constructor is marked protected and thus inaccessible by main.

like image 127
Hatted Rooster Avatar answered Oct 05 '22 02:10

Hatted Rooster


For the 2nd case, inheriting constructor doesn't take effect. According to the rules of deleted implicitly-declared default constructor, that in the 2nd case class D doesn't violate (there's a well-formed B::B() for D); the compiler will declare a default constructor as an inline public member for D, which makes D d{}; work well.

...

T has a direct or virtual base which has a deleted default constructor, or it is ambiguous or inaccessible from this constructor.

...

For the 1st case, inheriting constructors takes effect:

(emphasis mine)

If overload resolution selects an inherited constructor, it is accessible if it would be accessible when used to construct an object of the corresponding base class: the accessibility of the using-declaration that introduced it is ignored.

If overload resolution selects one of the inherited constructors when initializing an object of such derived class, then the Base subobject from which the constructor was inherited is initialized using the inherited constructor, and all other bases and members of Derived are initialized as if by the defaulted default constructor (default member initializers are used if provided, otherwise default initialization takes place).

Then it fails because of the access isolation.

like image 24
songyuanyao Avatar answered Oct 05 '22 02:10

songyuanyao