考虑如下代码,其中B
是D
通过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;
}
查看工作示例 here .我在 B
的构造函数中使用输出,并在 D
完全构造之后跟踪正在发生的事情。当我使用 g++-4.8.1 编译上述示例时,一切正常。它打印
99
Final: 99
因为 B
的构造函数从最派生类 (D
) 调用一次,这也决定了 x
的最终值。
现在是奇怪的部分:如果我换行
D() : B(99), B1(), B2() {}
到新的统一初始化语法,即
D() : B{99}, B1{}, B2{} {}
奇怪的事情发生了。一方面,它不再编译,出现错误
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{} {}
(对于 B2
也是如此,请参阅 here )这没有意义,因为我在派生类中使用它,所以 protected
应该没问题.如果我对此进行更正并使 B1
和 B2
的构造函数公开而不是 protected ,那么随着输出变为
99
0
10
Final: 10
所以,其实B1
s和B2
s构造函数中初始化B
的部分还是会被执行,甚至会改变x
。这不应该是虚拟继承的情况。请记住,我唯一改变的地方是
B1
和B2
中的公共(public)构造函数而不是 protected 构造函数
- 在
D
的成员初始化列表中使用classname{}
语法,而不是classname()
。
我无法相信 gcc 中出现了这样一个基本的问题。但是我在本地机器上用 clang 对其进行了测试,所有三个案例都按预期编译和运行(即像上面的第一个示例一样)。如果这不是错误,有人可以指出我所缺少的吗?
编辑:我的第一次搜索不知何故没有出现,但现在我找到了 here ,至少显示 protected /公共(public)错误。然而,这是 gcc-4.7,所以我原以为它会在 gcc-4.8 中处理。那么,我是否应该得出结论,初始化列表在 gcc 中根本就搞砸了!?
最佳答案
我不知道现在回答这个问题是否为时已晚,但您的代码在 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.
关于c++ - gcc中的初始化列表错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26914076/