将指向部分构造对象的指针转换为指向基类的指针是否合法?
也就是说,这样的事情总是合法的吗?
struct Derived;
struct Base { Base(Derived*); };
struct Derived : Base { Derived() : Base(this) { } };
Base::Base(Derived *self) {
if(static_cast<Base*>(self) != this) std::terminate();
}
int main() {
Derived d; // is this well-defined to never call terminate?
}
在static_cast求值时,self还没有指向一个Derived对象——那个对象正在构建中。例如,如果Derived有数据成员,它们的构造函数就不会被调用。是否仍然保证强制转换是定义的行为,从而产生一个与Base's等效的指针this(它确实指向一个完全构造的Base基类子对象)?
我认为接近回答这个问题的标准引语是[conv.ptr]/3。
...转换的结果是一个指向派生类对象的基类子对象的指针。...
但我认为是没有派生类对象还没有,那么会发生什么?如果它确实是未定义的,答案会改变self != static_cast<Derived*>(this)吗?
(Clang 和 GCC 编译并“按预期”运行。)