Is converting a reinterpret_cast'd derived class pointer to base class pointer undefined behavior?

gez*_*eza 11 c++ language-lawyer

Have a look at is simple example:

struct Base { /* some virtual functions here */ };
struct A: Base { /* members, overridden virtual functions */ };
struct B: Base { /* members, overridden virtual functions */ };

void fn() {
    A a;
    Base *base = &a;
    B *b = reinterpret_cast<B *>(base);
    Base *x = b;
    // use x here, call virtual functions on it
}
Run Code Online (Sandbox Code Playgroud)

Does this little snippet have Undefined Behavior?

reinterpret_cast定义明确,它返回的值不变base,只是类型为B *

但是我不确定这Base *x = b;条线。它使用b,类型为B *,但实际上指向一个A对象。而且我不确定是否x是“适当的” Base指针,是否可以使用它调用虚拟函数。

n. *_* m. 4

static_cast(或隐式派生到基指针的转换,其作用完全相同)与reinterpret_cast. 无法保证基本子对象与完整对象的起始地址相同。

大多数实现将第一个基子对象放置在与完整对象相同的地址处,但当然,即使这样的实现也不能将两个不同的非空基子对象放置在同一地址处。(具有虚函数的对象不为空)。当基子对象与完整对象不在同一地址时,static_cast不是空操作,它涉及指针调整。

有些实现甚至不会将第一个基本子对象放置在与完整对象相同的地址处。例如,允许将基本子对象放置在派生的所有成员之后。IIRC Sun C++ 编译器曾经以这种方式布局类(不知道它是否仍在这样做)。在这样的实现中,这段代码几乎肯定会失败。

B 具有多个碱基的类似代码在许多实现中都会失败。例子