gcc中的初始化列表错误?

Ogu*_*guk 12 c++ gcc initializer-list c++11

请考虑以下代码,其中BD通过B1和继承的虚拟基类B2:

#include <iostream>

class B
{
protected:
    int x;

protected:

    B(int x) : x{x}{std::cout << x << std::endl;}
};

class B1 : virtual public B
{
protected:

    B1() : B(0){}
};

class B2 : virtual public B
{
protected:

    B2() : B(10){}
};

class D : public B1, public B2
{
public:

    D() : B(99), B1(), B2() {}
    void print() {std::cout << "Final: " << x << std::endl;}
};

int main() {
    D d;
    d.print();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

见工作示例这里.我在B构造函数中使用了输出,之后D完全构造了以跟踪正在发生的事情.当我使用g ++ - 4.8.1编译上面的例子时,一切正常.它打印

99
Final: 99
Run Code Online (Sandbox Code Playgroud)

因为Bs构造函数从最派生的类(D)调用一次,并且还确定了最终的值x.

现在出现了奇怪的部分:如果我改变了这条线

D() : B(99), B1(), B2() {}
Run Code Online (Sandbox Code Playgroud)

到新的统一初始化语法,即

D() : B{99}, B1{}, B2{} {}
Run Code Online (Sandbox Code Playgroud)

奇怪的事发生了.首先,它不再编译,错误

prog.cpp: In constructor ‘D::D()’:
prog.cpp:17:5: error: ‘B1::B1()’ is protected
     B1() : B(0){}
     ^
prog.cpp:31:27: error: within this context
     D() : B{99}, B1{}, B2{} {}
Run Code Online (Sandbox Code Playgroud)

(并且相同B2,见,这里)因为我在派生类中使用它没有意义,所以protected应该没问题.如果我纠正了这个并且使构造函数B1B2public而不是protected,那么一切都会变得混乱(参见这里),因为输出变为

99
0
10
Final: 10
Run Code Online (Sandbox Code Playgroud)

所以,事实上,初始化的B1s和B2s构造函数的B部分仍然被执行,甚至改变了它的值x.这不应该是虚拟继承的情况.请记住,我唯一改变的

  • 公开,而不是在受保护的构造B1B2
  • classname{}在成员初始化列表中使用语法D而不是classname().

我不敢相信这个基本的东西在gcc中出错了.但我在我的本地机器上用clang测试它,在那里,所有三种情况都按预期编译和运行(即像上面的第一个例子).如果它不是一个错误,有人可以指出我错过了什么?

编辑:我的第一次搜索没有提出,但现在我发现了另一个问题,至少显示受保护/公共错误.但是,这是gcc-4.7,所以我原本预计它会在gcc-4.8中处理.那么,我是否应该总结一下初始化列表在gcc中根本搞砸了!?

Con*_*nos 1

我不知道现在回答这个问题是否太晚了,但是你的代码在 GCC 4.9.2 中编译得很好!

~$g++ -std=c++11 test.cpp 
~$./a.out 
99
Final: 99

~$gcc --version
gcc (GCC) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Run Code Online (Sandbox Code Playgroud)