[...]命名构造函数的using声明不会创建同义词;相反,如果在用于构造相应基类的对象时可以访问附加构造函数,则可以访问这些附加构造函数,并忽略using-declaration的可访问性。 [...]
因此,以下代码无法编译:
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{}; }
由于导致上一个示例中出错的相同原因,不能编译失败吗?
它允许编译什么?
答案 0 :(得分:6)
class B { protected: B() { } };
class D: B { using B::B; };
int main () { D d{}; }
在这种情况下, D
没有用户定义的构造函数,因此编译器为您生成一个(公共)调用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
无法访问。
答案 1 :(得分:3)
对于第二种情况,继承构造函数不会生效。根据{{3}}的规则,在第2个案例类D
中没有违反(B::B()
的格式D
;编译器会将默认构造函数声明为D
的内联公共成员,这使D d{};
运行良好。
...
T
具有直接或虚拟基础,其具有已删除的默认构造函数,或者此构造函数不明确或无法访问。...
对于第一种情况,deleted implicitly-declared default constructor生效:
(强调我的)
如果重载决策选择了继承的构造函数,那么它就是 如果在用于构造对象时可访问它,则可访问 对应的基类:的可访问性 引入它的using声明被忽略。
如果重载决策选择了其中一个继承的构造函数 初始化此类派生类的对象,然后是Base子对象 从中使用。来初始化构造函数的继承 继承的构造函数,以及Derived的所有其他基础和成员 初始化,好像是默认的默认构造函数(默认成员 如果提供,则使用初始化程序,否则默认初始化 发生)。
然后由于访问隔离而失败。