【问题标题】:Inherited constructors, default constructor and visibility继承构造函数、默认构造函数和可见性
【发布时间】:2016-10-17 08:42:34
【问题描述】:

[namespace.udecl]/18所述:

[...] 命名构造函数的 using 声明不会创建同义词;相反,如果附加构造函数在用于构造相应基类的对象时可访问,则它们是可访问的,并且忽略 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 没有用户声明的构造函数。
  • @T.C.我也是这么想的,但是using-declaration的可访问性被忽略了,那么在第二种情况下不应该继承和保护默认构造函数吗?
  • 好的,另一个提示。如果类没有用户声明的构造函数,[class.ctor]/4 会说什么?在给定 [namespace.udecl]/15 的情况下,它如何与基类构造函数交互?
  • 顺便说一句,只有 Clang 3.9 实现了 P0136R1 语义(您正在引用)。旧规则根本不继承默认构造函数。
  • @T.C.因此,您隐含地说默认构造函数不是继承的,即使是用户定义的构造函数也是如此。或者更好的是,当我们寻找使用定义的构造函数时,继承的构造函数不参与。对吗?

标签: c++ c++11 language-lawyer default-constructor inherited-constructors


【解决方案1】:
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 也有一个构造函数,它接受 intusing 做到了),但这个构造函数被标记为 protected,因此 main 无法访问。

【讨论】:

    【解决方案2】:

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

    ...

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

    ...

    第一种情况,inheriting constructors生效:

    (强调我的)

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

    如果重载决议选择继承的构造函数之一,当 初始化此类派生类的对象,然后是 Base 子对象 从中继承构造函数的初始化使用 继承的构造函数,以及 Derived 的所有其他基类和成员 如同由默认的默认构造函数(默认成员 如果提供,则使用初始化器,否则使用默认初始化 发生)。

    然后因为访问隔离而失败。

    【讨论】:

    • 关于复制/移动的规则来自here,但是关于默认规则的规则来自哪里?
    • @skypjack 重点是在第二种情况下会为D类生成一个默认构造函数,除了继承构造函数之外,它会生效。答案固定。
    猜你喜欢
    • 2016-03-24
    • 2015-07-09
    • 1970-01-01
    • 2018-04-18
    • 2016-12-05
    • 2021-06-02
    • 2017-10-04
    相关资源
    最近更新 更多