在示例中使用 static_cast 没问题,但reinterpret_cast 则不行。因为reinterpret_cast不是转换vtable。
No, the problem is that the reinterpret_cast
is completely oblivious about the inheritance. It will simply return the same address unchanged1. But static_cast
knows that you're performing a downcast: i.e. casting from a base class to a derived class. Since it knows both types involved it adjusts the address accordingly, i.e., does the right thing.
Let's pretend我们的实施提出了假设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
knows来转换一个OVERLAPPED*
to OVERLAPPEDEX*
它必须调整地址,并做正确的事情:
+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------------+------------------+-------------+
^
|
ptr after static_cast
不过,如果我在那里使用 C 风格的强制转换(而不是reinterpret_cast),它也会出错吗?
C 风格强制转换被定义为以下第一个成功的转换:
const_cast
static_cast
-
static_cast
, then const_cast
reinterpret_cast
-
reinterpret_cast
, then const_cast
如您所见,一个static_cast
之前尝试过reinterpret_cast
,所以在这种情况下,C 风格的强制转换也会做正确的事情。
更多信息
1Not guaranteed. There are very little guarantees about what happens on a reinterpret_cast
. All implementations I know of will simply give out the same address unchanged.