1

次の例は、12.7/3 N3797 に記載されています。

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
    }
};

例のルール:

クラス X のオブジェクトを参照するポインター (glvalue) を、X の直接的または間接的な基底クラス B へのポインター (参照) に明示的または暗黙的に変換するには、X の構築と、その直接的または間接的な基底すべての構築B から直接的または間接的に派生するクラスが開始され、これらのクラスの破棄が完了していない必要があります。そうでない場合、変換によって未定義の動作が発生します。

しかし、例を少し変更してみましょう:

struct A { };
struct HD { }; // will be used as a base for D
struct B : virtual A { };
struct C : B { };
struct D : HD, virtual A { D(A*); };
struct X { X(A*); };
struct E : C, D, X {
    E() : D(this), // 1. Is there undefined behavior? 
                   // I think, there isn't.
    X(this) {
    }
};

コンストラクターの呼び出し前に構築された//1クラスの基本サブオブジェクトがあるため、UB はないと思います。つまり、D(A*) が呼び出された時点で、 の構築が開始されます。HDD(A*)D

私の推論は正しいですか?

4

0 に答える 0