继承构造函数、默认构造函数和可见性

Inherited constructors, default constructor and visibility

[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. [...]

因此,以下代码无法编译:

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

它 returns 一个与所有主要编译器大致相同的错误:

declared protected here

在另一边,编译以下代码:

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

它不应该因为与上一个示例中导致错误的相同原因而编译失败吗?
它允许编译什么?

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

D 在这种情况下没有用户定义的构造函数,因此编译器会为您生成一个 (public) 来调用 B::B(但不是因为 using,在这种情况下没有效果),然后由 main 调用编译器生成的构造函数。

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

尽管 D 这里没有用户定义的构造函数,但编译器生成的构造函数被隐式删除,因为 B 只有一个采用 int 的构造函数。 D 也有一个采用 int 的构造函数(using 做到了)但是这个构造函数被标记为 protected 因此 main.[=23 无法访问=]

对于第二种情况,继承构造函数不生效。根据 deleted implicitly-declared default constructor 的规则,在第二种情况下 class D 没有违反(D 有一个格式良好的 B::B());编译器将声明一个默认构造函数作为 D 的内联 public 成员,这使得 D d{}; 工作良好。

...

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

...

对于第一种情况,inheriting constructors生效:

(强调我的)

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).

然后由于访问隔离而失败。