以下示例在 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 类对象的指针(泛左值)转换为指向 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,因为我们有HD
在调用构造函数之前构建的类的基本子对象D(A*)
。也就是说,在 D(A*) 调用时, 的构造D
已经开始。
我的推理正确吗?