Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't an inherited protected constructor be made public?

Consider:

class A
{
protected:
    A(int) {}
    void f(int) {}

public:
    A() {}
};

class B : public A
{
public:
    using A::A;
    using A::f;
};

int main()
{
    B().f(1); // ok
    B(1); // error: 'A::A(int)' is protected within this context
}

Why can't an inherited protected constructor be made public, while an inherited protected member function can?

like image 832
xmllmx Avatar asked May 30 '20 07:05

xmllmx


Video Answer


2 Answers

Unlike other members, the accessibility of the using-declaration that introduced the inherited constructor is ignored.

[namespace.udecl]/19,

(emphasis mine)

A synonym created by a using-declaration has the usual accessibility for a member-declaration. A using-declarator 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.

like image 102
songyuanyao Avatar answered Sep 25 '22 15:09

songyuanyao


Actually, the inherited constructor can be made public, but not just the way you wrote it. You can define your B class as follows:

class B : public A {
public:
    B() {}

    B(int x) : A(x) {}  // instead of using A::A(int)
    using A::f;
};

(see it on GodBolt)

Perhaps the standard committee thought that saying using A::A would be a bit ambiguous, since a constructor of the base class is not exactly the same thing as a constructor of the subclass.

like image 3
einpoklum Avatar answered Sep 23 '22 15:09

einpoklum