C++ 在构造过程中隐式转换为基类
12.7/3中给出了以下示例:C++ 在构造过程中隐式转换为基类,c++,C++,12.7/3中给出了以下示例: 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* →
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
}
};
示例的规则如下所示:
显式或隐式转换引用的指针(glvalue)
指向指向直接或间接对象的指针(引用)的X类对象
X的基类B,X的构造和所有的构造
其直接或间接派生的直接或间接基础
从B开始,这些等级的破坏应
尚未完成,否则转换将导致未定义
行为
在标准提供的情况下,我们有A派生类的列表是
{B,D,C,E}
。A
、C
和B
的建设已经完成。但是D
的构建已经开始,此时我们需要使用E*→ D*→ A*
。那么为什么行为实际未定义呢?到A*
的转换是一个参数计算,必须在结果传递给D
构造函数之前完成。因此,D
构造尚未开始。作为反例,E
的构造此时已开始,但尚未完成。在转换发生后,D
的构造从实际调用D
的构造函数的点开始。