c++中的虚拟继承和统一初始化
Virtual inheritance and uniform initialization in C++
关于多重(虚拟)继承的问题,我想询问一个简单的MWE,它使g++ 5.2.0感到不安,而clang++ 3.6.2处理得很好,没有任何抱怨,即使设置了-Wall
和-Wextra
。这是MWE:
class Z {};
class A : virtual Z { protected: A() {} };
class B : virtual Z { protected: B() {} };
class C : A, B { public: C() : A{}, B{} {} };
int main() { C c{}; return 0; }
与clang++不同,g++抱怨如下:
gccodd.c++: In constructor ‘C::C()’:
gccodd.c++:2:34: error: ‘A::A()’ is protected
class A : virtual Z { protected: A() {} };
^
gccodd.c++:4:39: error: within this context
class C : A, B { public: C() : A{}, B{} {} };
^
gccodd.c++:3:34: error: ‘B::B()’ is protected
class B : virtual Z { protected: B() {} };
^
gccodd.c++:4:39: error: within this context
class C : A, B { public: C() : A{}, B{} {} };
^
用旧的形式替换C构造函数中的统一初始化可以很好地工作,clang++和g++都对以下内容很满意:
class C : A, B { public: C() : A(), B() {} };
这产生两个明显的选项:
- 代码在某种程度上违反了标准,使得结果未定义(即,任何结果都可以接受)。
- 两个编译器之一有一个与统一初始化和多重虚拟继承相关的错误。
如果这是一个投票的问题,(1)可能会赢,因为icpc 15.0.0说:
gccodd.c++(4): error #453: protected function "A::A()" (declared at line 2) is not accessible through a "A" pointer or object
class C : public virtual A, public virtual B { public: C() : A{}, B{} {} };
^
gccodd.c++(4): error #453: protected function "B::B()" (declared at line 3) is not accessible through a "B" pointer or object
class C : public virtual A, public virtual B { public: C() : A{}, B{} {} };
^
那么,它是(1)还是(2)?如果是前一种情况,那么我的MWE有什么问题?
list -定义
T
类型的对象或引用的初始化为
(3.1)—如果T
是一个类类型并且初始化列表有cvU
[..]]
(3.2) -否则,如果T
是a字符数组[…]
(3.3) -否则,如果T是一个集合,执行聚合初始化(8.5.1)。
(3.4) - 否则,if初始化列表没有元素,T
是一个类类型
A
和B
都有基类,因此不是聚合。所以第四个要点适用。这样我们就得到了和使用()
:
初始化式为一组空括号的对象,即:
()
,必须值初始化
任何使用这些初始化式产生不同结果的编译器都不能是一致的。
§11.4处理对protected
成员的访问,没有提到任何与初始化形式相关的内容。然而,关于构造函数中mem初始化式中的基的初始化,第11.4节目前是有缺陷的,正如CWG问题#1883所提到的。
相关文章:
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 为什么除了继承聚合结构之外,结构为空,无法聚合初始化?
- 初始化依赖于子类的继承类的常量类成员
- C++ 初始化继承的模板基类
- 使用继承初始化C++中的参数
- 我是否需要在虚拟继承类的构造函数中初始化基类以解决菱形继承问题?
- 继承的构造函数忽略类内初始化
- 是否可以在不修改父类的情况下将成员变量初始化推迟到继承的类?
- 跨继承树初始化元组
- 与lambda一起使用虚拟继承在初始化列表中捕获此问题的GCC错误
- GCC:当层次结构中存在虚拟继承时,C++11 内联对象初始化(使用 "this")不起作用
- 如何在派生类中初始化继承的模板POD结构
- 我如何避免明确构建C 初始化列表中继承的所有内容
- 使用从另一个类继承的类的对象初始化成员对象
- 正确的语法,用于在C 中继承,并具有初始化列表和内存分配
- 构造函数继承和直接成员初始化
- 继承构造函数不允许类似数组的初始化
- valgrind 在使用 std::make_shared 和虚拟继承时报告的未初始化值
- 初始化继承的成员数据
- 如何初始化继承类的静态变量