为什么使用声明的继承构造函数不使用默认构造函数初始化虚拟基类?

汉森登

我在一个偶然的问题昨天通过声明的继承构造函数。在仔细阅读了答案以及链接的标准草案N3337之后,我发现当直接基类也用于using从虚拟基继承构造函数时,可能存在一些不一致(或至少是我的误解)

这是一个例子:

struct A
{
    A(int, int){}
};

struct B : virtual A
{
    using A::A;
};

struct C : virtual A
{
    using A::A;
};

struct BC : B, C
{
    using B::B;
    using C::C;
}; 

// Now if we define an inline constructor that does the same
// as the constructor B inherited...
struct BB : virtual A
{
    BB(int a, int b):A(a,b){}
};

struct BBC : BB, C
{
    using BB::BB;
    using C::C;
};

int main()
{
    BC(1, 1);  // this compiles
    BBC(1, 1); // this doesn't because it needs to defaultly
               // initialize the virtual base A who doesn't
               // have a default constructor
}

我了解为何BBC无法根据上述答案提供的确切原因进行编译,我将在此处重复[class.inhctor] / 8

隐式定义的继承构造函数将通过用户编写的内联构造函数对该类进行初始化,该类由用户编写的内联构造函数使用mem-initializer-list进行执行,该列表的唯一mem-initializer具有一个mem-initializer-id来命名使用声明的嵌套名称说明符中指定的基类,以及下面指定的表达式列表,并且其功能主体中的复合语句为空([class.base.init])。

[class.base.init] / 10

在非委托的构造函数中,初始化按以下顺序进行:首先,并且仅对于最派生类([intro.object])的构造函数,虚拟基类将按照它们出现在深度优先左侧的顺序进行初始化。基类的有向无环图的从右到右遍历,其中“从左到右”是基类在派生类base-specifier-list中的出现顺序。

因此,基本上,虚拟基类需要默认构造,因为它不在继承的构造函数mem-initializer-listBBC但是A没有默认的构造函数,因此会失败(添加A()=default;显然可以使其编译,但这不是重点)。

但是我还不清楚为什么BC没有这个问题?从本质上讲与cppreference在“继承的构造函数”部分给出的示例相同因此它必须工作。但这看起来与标准并不矛盾吗?B从中继承构造函数时A,除了非默认值外,它什么也不会得到,它与定义的默认值执行相同的初始化BB,只是隐式的。然后,当fromB进一步继承此构造方法时BC,难道不是同一规则适用于A默认构造的地方,因此无法编译吗?

编辑:@ j6t指出我正在看一个过时的标准草案。新的的确符合与cppreference页我发现较早更好。

我仍然不清楚的一件事是,它确实说明了如果选择了虚拟基础构造函数会发生什么情况,但是首先由孙子类继承的是什么BC从同一草稿开始,似乎using仅在派生类中考虑引入的虚拟基构造函数B在这种情况下)。如何usingBC继承一个构造函数,是上述两种电平?

我期望的是,在BC使用-declare构造函数时,最初由Bfrom继承的最初A应该被视为B构造函数,然后再由继承BC但是事实并非如此。

j6t

我只是在编辑中回答您的问题。

...但是首先,孙子类BC如何继承[虚拟基本构造函数]?

您引用段落说:

在查询派生类的构造函数(class.qual)[...]时,将使用using声明引入的构造函数视为派生类的构造函数

即,它说这些构造函数是通过限定名称查找找到的。这使use-declaration有效地进行了递归操作:要在基类中查找事物,它使用限定名称查找,然后将找到的事物用于限定名称查找。

struct B使用时using A::A在中查询构造函数A::A,它将使构造函数可用struct B这发生在struct BC使用时using B::B这是名合格的查找Bstruct B; 因此,它找到了构造函数A::A,并以这种方式在中A::A可用struct BC

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么派生类的构造函数在初始化列表中使用基类的默认构造函数?

来自分类Dev

为什么赋值初始化如果不使用它就需要复制构造函数

来自分类Dev

为什么不使用我的(模板)构造函数进行初始化?

来自分类Dev

为什么显式声明的构造函数阻止使用C ++ 11初始化列表进行成员初始化?

来自分类Dev

为什么显式声明的构造函数阻止使用C ++ 11初始化列表进行成员初始化?

来自分类Dev

用户声明的默认构造函数+类内初始化程序!=用户提供的构造函数?

来自分类Dev

为什么在构造函数初始化类的属性时声明其属性

来自分类Dev

为什么基类的成员不保留构造函数中首次初始化的值?

来自分类Dev

如何在不使用复制构造函数的情况下初始化类成员

来自分类Dev

在<jsp:useBean>中使用构造函数初始化类

来自分类Dev

使用构造函数初始化类中的指针

来自分类Dev

使用构造函数初始化类中的指针

来自分类Dev

为什么不使用Java 8中的默认构造函数?

来自分类Dev

为什么不能在类的构造函数的初始化列表中初始化ifstream?

来自分类Dev

继承构造函数和虚拟基类

来自分类Dev

继承构造函数和虚拟基类

来自分类Dev

是否可以在构造函数中使用this.fieldname初始化基类中的字段?

来自分类Dev

继承和复制构造函数-如何从基类初始化私有字段?

来自分类Dev

为什么C ++不使用父类构造函数?

来自分类Dev

具有类内初始化的默认默认构造函数的行为是什么?

来自分类Dev

为什么使用虚拟基类会更改复制构造函数的行为

来自分类Dev

为什么std :: atomic的默认构造函数不默认初始化底层存储值?

来自分类Dev

为什么就地成员初始化在C ++ 11中使用副本构造函数?

来自分类Dev

如何避免在基类初始化器中调用默认构造函数?

来自分类Dev

为什么使用声明生成的构造函数具有与基类相同的访问级别?

来自分类Dev

为什么使用声明生成的构造函数具有与基类相同的访问级别?

来自分类Dev

基本/默认构造函数与构造函数初始化列表

来自分类Dev

错误C2512:没有合适的默认构造函数-为什么在构造函数中初始化属性?

来自分类Dev

在初始化列表中使用空构造函数初始化父类?

Related 相关文章

  1. 1

    为什么派生类的构造函数在初始化列表中使用基类的默认构造函数?

  2. 2

    为什么赋值初始化如果不使用它就需要复制构造函数

  3. 3

    为什么不使用我的(模板)构造函数进行初始化?

  4. 4

    为什么显式声明的构造函数阻止使用C ++ 11初始化列表进行成员初始化?

  5. 5

    为什么显式声明的构造函数阻止使用C ++ 11初始化列表进行成员初始化?

  6. 6

    用户声明的默认构造函数+类内初始化程序!=用户提供的构造函数?

  7. 7

    为什么在构造函数初始化类的属性时声明其属性

  8. 8

    为什么基类的成员不保留构造函数中首次初始化的值?

  9. 9

    如何在不使用复制构造函数的情况下初始化类成员

  10. 10

    在<jsp:useBean>中使用构造函数初始化类

  11. 11

    使用构造函数初始化类中的指针

  12. 12

    使用构造函数初始化类中的指针

  13. 13

    为什么不使用Java 8中的默认构造函数?

  14. 14

    为什么不能在类的构造函数的初始化列表中初始化ifstream?

  15. 15

    继承构造函数和虚拟基类

  16. 16

    继承构造函数和虚拟基类

  17. 17

    是否可以在构造函数中使用this.fieldname初始化基类中的字段?

  18. 18

    继承和复制构造函数-如何从基类初始化私有字段?

  19. 19

    为什么C ++不使用父类构造函数?

  20. 20

    具有类内初始化的默认默认构造函数的行为是什么?

  21. 21

    为什么使用虚拟基类会更改复制构造函数的行为

  22. 22

    为什么std :: atomic的默认构造函数不默认初始化底层存储值?

  23. 23

    为什么就地成员初始化在C ++ 11中使用副本构造函数?

  24. 24

    如何避免在基类初始化器中调用默认构造函数?

  25. 25

    为什么使用声明生成的构造函数具有与基类相同的访问级别?

  26. 26

    为什么使用声明生成的构造函数具有与基类相同的访问级别?

  27. 27

    基本/默认构造函数与构造函数初始化列表

  28. 28

    错误C2512:没有合适的默认构造函数-为什么在构造函数中初始化属性?

  29. 29

    在初始化列表中使用空构造函数初始化父类?

热门标签

归档