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

标签 c++ c++11 constructor standards implicit-conversion

  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 段开头下方找到:

To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a pointer (reference) to a direct or indirect base class B of X, the construction of X and the construction of all of its direct or indirect bases that directly or indirectly derive from B shall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior.

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

struct Base{ Base(Base*); };

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

最佳答案

What are the specific problems that are being avoided with the restrictions imposed by this clause 12.7p3 (see the first part of paragraph below)?

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

In the example shown in 12.7p3 (see below) why X(this) is considered defined? Is it because X is not in the path E C D B A ?

因为基类构造函数是按照它们在类声明中出现的顺序调用的(即 struct E : C, D, X {)。因为基类C和D都被构造了,所以它们共同的虚基类A当然也被构造了。并且因为 X 没有继承自 A 类,这意味着在从类 E 执行转换时有一个完全构造且明确的路径在这一点上类A。这就是这条线定义明确的原因。

Is it correct to say that the set of all direct and indirect bases of X, mentioned above don't include B, and because of this the code below is well defined, notwithstanding the fact that Base is a direct base of Derived and has yet not started?

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

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

关于c++ - 关于 C++ 标准中的第 12.7p3 段,我有以下问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16308372/

相关文章:

c++ - 给定复制构造的要求,如何在 C++11 中编写有状态分配器?

c++ - 写入另一个类的类中的变量

c++ - 验证给定 C++ 编译器是否将源代码读取为 C++11 的快速简单代码是什么?

c++ - 为什么两次使用 ifstream 对象会导致错误?

c++ - `std::mutex` 和 `std::lock` 是否保证处理器间代码中的内存同步?

c++ - 如何使用带参数的构造函数创建对象

java - Java构造函数困惑

c++ - 构造函数的类型是什么?

c++ - 将缺少的左括号添加到等式中

c++ - 如何防止在 C++ 中重复随机生成的选项?