c++中的虚拟继承和统一初始化

Virtual inheritance and uniform initialization in C++

本文关键字:初始化 继承 虚拟 c++      更新时间:2023-10-16

关于多重(虚拟)继承的问题,我想询问一个简单的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. 代码在某种程度上违反了标准,使得结果未定义(即,任何结果都可以接受)。
  2. 两个编译器之一有一个与统一初始化和多重虚拟继承相关的错误。

如果这是一个投票的问题,(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是一个类类型并且初始化列表有cv U [..]]
(3.2) -否则,如果T是a字符数组[…]
(3.3) -否则,如果T是一个集合,执行聚合初始化(8.5.1)。
(3.4) - 否则,if初始化列表没有元素,T是一个类类型

AB都有基类,因此不是聚合。所以第四个要点适用。这样我们就得到了和使用():

相同的效果

初始化式为一组空括号的对象,即:(),必须值初始化

任何使用这些初始化式产生不同结果的编译器都不能是一致的。

§11.4处理对protected成员的访问,没有提到任何与初始化形式相关的内容。然而,关于构造函数中mem初始化式中的基的初始化,第11.4节目前是有缺陷的,正如CWG问题#1883所提到的。