关于C++标准第12.7p3段,我有以下问题

In relation to the paragraph 12.7p3 in the C++ Standard, I have the following questions

本文关键字:问题 标准 C++ 7p3 关于      更新时间:2023-10-16
  1. 12.7p3条施加的限制避免了哪些具体问题(见下文段落第一部分(?

  2. 12.7p3 所示的示例中(见下文(,为什么X(this)被视为已定义?是因为X不在路径E C D B A吗?

    struct A { };
    struct B : virtual A { };
    struct C : B { };
    struct D : virtual A { D(A*); };
    struct X { X(A*); };
    struct E : C, D, X {
    E() : D(this),  // undefined: upcast from E* to A*
                    // might use path E* - D* - A*
                    // but D is not constructed
                    // D((C*)this), // defined:
                    // E* - C* defined because E() has started
                    // and C* - A* defined because
                    // C fully constructed
          X(this) { // defined: upon construction of X,
                    // C/B/D/A sublattice is fully constructed
        }
    };
    
  3. 请在下面找到第12.7p3段的开头:

显式或隐式转换引用 指向直接或间接指针(引用(的 X 类对象 X的基类B,X的构造和所有构造 直接或间接得出的 从B开始,这些类的销毁应该 尚未完成,否则转换结果为 undefined 行为。

上面提到的所有直接和间接X基础的集合不包括B,因此下面的代码定义得很好,尽管BaseDerived的直接基础并且尚未开始,这是否正确?

struct Base{ Base(Base*); };
struct Derived : Base {
    Derived() : Base(this) {};
};

第12.7p3条施加的限制避免了哪些具体问题(见下文段落的第一部分(?

这些问题与以下

事实有关:在某些时候,必须为派生类初始化虚拟指针(指向虚拟表或虚拟基类(。这是在"初始化列表"期间(即,在构造函数体开始之前(发生的初始化,通常是在构造基类之后(例如,在构造基类 B 之后,为类 X 设置虚拟表指针和可能的虚拟基指针,然后初始化数据成员,然后构造函数的主体开始(。通常,在初始化这些指针之前执行向上转换将产生未定义的行为,因为无法对虚拟基执行所需的指针查找,或者未正确设置虚拟表指针以正确调用虚拟函数。

在 12.7p3 所示的示例中(见下文(,为什么 X(this( 被认为是定义的?是因为 X 不在路径 E C D B A 中吗?

因为基类构造函数是按照它们在类声明中出现的顺序(即 struct E : C, D, X { (调用的。因为基类 C 和 D 都是构造的,所以它们的公共虚拟基类 A 当然也是构造的。而且由于X不继承自类A,这意味着此时在执行从类E到类A的转换时,存在一条完全构造且明确的路径。这就是为什么这条线是明确界定的。

说上面提到的 X 的所有直接和间接基的集合不包括 B,因此下面的代码定义得很好,尽管 Base 是 Derived 的直接基并且尚未开始,这是否正确?

不确定我是否遵循您的解释,但我可以告诉您,您显示的代码没有明确定义。当通过强制Derived* this来调用Base的构造函数时Base*,派生类中的基类对象尚未构造,因此,强制转换是未定义的。

此代码有意义的唯一方法是,如果层次结构中不涉及虚函数或虚拟基类,在这种情况下,将不需要此类代码,因为指向基类的this指针已隐式发送到基类构造函数。