8

[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{}; }

它不应该因为与前面示例中导致错误相同的原因而无法编译吗?
它允许它编译什么?

4

2 回答 2

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( usingdid that) 但是这个构造函数被标记protected,因此不能被main.

于 2016-10-17T08:57:29.803 回答
3

对于第二种情况,继承构造函数不生效。根据删除隐式声明的默认构造函数的规则,在第二种情况下,类D不违反(有一个格式良好的B::B()for D);编译器会将默认构造函数声明为 的内联公共成员D,这样可以D d{};正常工作。

...

T有一个直接的或虚拟的基础,它有一个已删除的默认构造函数,或者它不明确或无法从此构造函数访问。

...

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

(强调我的)

如果重载决议选择了一个继承的构造函数,如果它在用于构造相应基类的对象时是可访问的,则它是可访问的:引入它的 using 声明的可访问性被忽略

如果在初始化此类派生类的对象时重载决策选择了继承的构造函数之一,则使用继承的构造函数初始化继承构造函数的 Base 子对象,并且 Derived 的所有其他基类和成员都像默认值一样初始化默认构造函数(如果提供,则使用默认成员初始化器,否则会发生默认初始化)。

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

于 2016-10-17T09:02:17.707 回答