使用 static_cast 在这个例子中是可以的,但是 reinterpret_cast 不行。因为 reinterpret_cast 无法转换虚函数表。
不,问题在于 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
知道将OVERLAPPED*
转换为OVERLAPPEDEX*
时必须调整地址,并且会执行正确的操作:
+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+
^
|
ptr after static_cast
尽管如此,在那里使用C风格转换(而不是reinterpret_cast),它也可能出错吗?
C风格转换被定义为以下第一个成功的转换之一:
1. const_cast
2. static_cast
3. static_cast,然后const_cast
4. reinterpret_cast
5. reinterpret_cast,然后const_cast
正如您所看到的,在尝试reinterpret_cast之前会尝试static_cast,因此在这种情况下,C风格转换也会做正确的事情。
更多信息
1不保证。在使用reinterpret_cast
时,关于其发生的结果几乎没有任何保证。所有我所知道的实现都只是简单地返回相同的地址,不做任何修改。
*(destination_type *)&
。可以想象,“static cast”实际上考虑了类之间的关系,并允许编译器进行非平凡的转换工作。 - R.. GitHub STOP HELPING ICE