从指向派生 class 的指针的 `static_cast<Base*>(static_cast<void*>(derived)) 什么时候有效?

When is a `static_cast<Base*>(static_cast<void*>(derived))` from a pointer to a derived class valid?

本题不涉及多态,即不涉及虚方法,不涉及虚基classes。以防万一,我的案子不涉及这些。

假设我有一个 class Derived,它有一个 Base 类型的明确可访问 parent,没有多态性(没有虚方法,没有虚基 classes),但可能涉及间接 and/or 多重继承。 进一步假设我有一个有效的指针 Derived *derived (指向类型 Derived 的 object 或其子 class)。

在这种情况下,我相信 static_cast<Base*>(derived) 是有效的 (导致有效的可用指针)。当 BaseDerived 之间的祖先链涉及多重继承时,此 static_cast 可能意味着指针调整以在 Derived 实例中定位 Base 实例。为此,编译器需要知道继承链,他在本例中就是这样做的。但是,如果插入到 void * 的中间转换,则该继承链信息对编译器是隐藏的。对于哪个继承链,这样的静态转换仍然有效?我期望以下之一:

static_cast<Base*>(static_cast<void*>(derived)) 在 C++ 标准中有一个名称。它被称为 reinterpret_cast。它在 [expr.reinterpret.cast] paragraph 7:

中指定

An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_­cast<cv T*>(static_­cast<cv void*>(v)). [ Note: Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. — end note ]

A reinterpret_cast 是我们告诉编译器将指针视为其他东西。编译器无法或将根据此指令进行任何调整。如果我们撒谎,那么行为就是未定义的。标准是否说明这样的 reinterpret_cast 何时有效?它确实如此。 [basic.compound] paragraph 4:

中定义了指针互换性的概念

Two objects a and b are pointer-interconvertible if:

  • they are the same object, or
  • one is a union object and the other is a non-static data member of that object ([class.union]), or
  • one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, any base class subobject of that object ([class.mem]), or
  • there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.

If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_­cast. [ Note: An array object and its first element are not pointer-interconvertible, even though they have the same address. — end note ]

第三个项目符号就是你的答案。 class 层次结构中的对象必须遵守限制(standard layout 从顶层到最派生),只有这样才能保证转换给出明确定义的结果。