继承的构造函数,默认构造函数和可见性 [英] Inherited constructors, default constructor and visibility

查看:125
本文介绍了继承的构造函数,默认构造函数和可见性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[namespace.udecl]/18 所述:

[...]命名构造函数的使用声明不会创建同义词.相反,如果其他构造函数在构造相应基类的对象时可以访问,则可以访问这些附加构造函数,并且using-声明的可访问性将被忽略. [...]

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

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

它返回的错误与所有主要编译器大致相同:

此处声明受保护

另一方面,将编译以下代码:

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

不是因为导致上一个示例错误的原因而无法编译吗?
它允许编译什么?

解决方案

在第二种情况下,继承构造函数无效.根据删除隐式声明的默认构造函数的规则,在第二种情况下,类D没有违反(D有一个格式正确的B::B());编译器将声明默认构造函数为D的内联公共成员,这使D d{};正常工作.

...

T具有直接或虚拟基础,该基础具有已删除的默认构造函数,或者该构造函数不明确或无法访问.

...

对于第一种情况,继承构造函数生效:

(重点是我的)

如果重载分辨率选择了继承的构造函数,则为 如果在构造对象时可以访问,则可访问 相应基类的: .

如果重载解析在以下情况下选择了继承的构造函数之一 初始化此类派生类的对象,然后初始化Base子对象 使用初始化从其继承构造函数的方法 继承的构造函数,而所有其他派生基和成员都是 好像由默认的默认构造函数(默认成员)初始化 如果提供,则使用初始化程序,否则使用默认初始化 发生.)

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

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?

解决方案

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.

这篇关于继承的构造函数,默认构造函数和可见性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆