在示例中使用 static_cast 很好,但 reinterpret_cast 不是。因为 reinterpret_cast 不是转换 vtable。
不,问题在于reinterpret_cast
完全不知道继承。它将简单地返回相同的地址不变1。但static_cast
知道您正在执行向下转换:即从基类转换为派生类。由于它知道涉及的两种类型,因此它会相应地调整地址,即做正确的事情。
让我们假设我们的实现展示了OVERLAPPEDEX
具有如下虚函数的假设类:
+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------------+------------------+-------------+
^
|
ptr
我们得到的指针指向OVERLAPPED
子对象。reinterpret_cast
不会改变这一点。它只会改变类型。显然,OVERLAPPEDEX
通过这个地址访问这个类很容易造成破坏,因为它的子对象的位置现在都错了!
what we believe we have when we access OVERLAPPEDEX through the pointer
+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------+-----+------+-----------+------+------+------+
| vptr | OVERLAPPED | AssociatedClient | ClientState | <- what we actually have
+------+------------+------------------+-------------+
^
|
ptr
static_cast
知道要将 a 转换OVERLAPPED*
为OVERLAPPEDEX*
它必须调整地址,并且做正确的事情:
+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------------+------------------+-------------+
^
|
ptr after static_cast
不过,如果我在那里使用 C-Style cast(不是 reinterpret_cast),它也会出错吗?
C 样式转换定义为以下第一个成功的转换:
const_cast
static_cast
static_cast
, 然后const_cast
reinterpret_cast
reinterpret_cast
, 然后const_cast
如您所见, astatic_cast
是在之前尝试过reinterpret_cast
的,因此在这种情况下,C 风格的演员表也会做正确的事情。
更多信息
1不保证。关于在reinterpret_cast
. 我所知道的所有实现都会简单地给出相同的地址不变。