为什么在这里使用static_cast而不是reinterpret_cast很重要?

Ben*_*min 9 c++ pointers casting static-cast reinterpret-cast

在Raymond Chen的博客文章的回复中,

一位提问者指出

Raymond,我认为C++示例不正确,因为根据ISO C++ 2003 Standard(10-3,第168页)未定义派生类中基类子对象的位置,并且您假设基类子对象始终位于一开始.C语言中的C语言也没问题,所以我坚持下去.

雷蒙德回答说

[代码没有做出这个假设.这就是使用static_cast而不是reinterpret_cast的重要原因.试一试:向OVERLAPPED添加一个虚方法(所以vtable在前面)并观察编译器的作用.-Raymond]

读完他的评论后,我猜错了.在示例中使用static_cast很好,但是reinterpret_cast不是.因为reinterpret_cast不能转换为vtable.我理解得对吗?
虽然,如果我在那里使用C-Style演员(不是reinterpret_cast),它也会出错吗?

我重新阅读了更有效的C++演员解释,以了解这一点.但是没有答案.

R. *_*des 17

在示例中使用static_cast很好,但是reinterpret_cast不是.因为reinterpret_cast不能转换为vtable.

不,问题在于reinterpret_cast遗传完全没有意识到.它只会返回相同的地址1.但是static_cast 知道你正在执行一个向下转换:即从基类转换为派生类.因为它知道所涉及的两种类型,所以它相应地调整地址,即做正确的事情.

让我们假设我们的实现列出了OVERLAPPEDEX具有如下虚函数的假设类:

+------+------------+------------------+-------------+
| vptr | OVERLAPPED | AssociatedClient | ClientState |
+------+------------+------------------+-------------+
       ^
       |
      ptr
Run Code Online (Sandbox Code Playgroud)

我们给出的指针指向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
Run Code Online (Sandbox Code Playgroud)

static_cast 知道要转换OVERLAPPED*OVERLAPPEDEX*它必须调整地址,并做正确的事情:

 +------+------------+------------------+-------------+
 | vptr | OVERLAPPED | AssociatedClient | ClientState |
 +------+------------+------------------+-------------+
 ^
 |
ptr after static_cast
Run Code Online (Sandbox Code Playgroud)

虽然,如果我在那里使用C-Style演员(不是reinterpret_cast),它也会出错吗?

C样式强制转换定义为以下第一个成功:

  1. const_cast
  2. static_cast
  3. static_cast, 然后 const_cast
  4. reinterpret_cast
  5. reinterpret_cast, 然后 const_cast

正如你所看到的,static_cast之前尝试过a reinterpret_cast,所以在这种情况下,C风格的演员也会做正确的事情.


更多信息


1 不保证.对于发生的事情几乎没有什么保证reinterpret_cast.我所知道的所有实现都会简单地给出相同的地址.