2012-02-04 79 views
9

At a reply of a blog post of Raymond Chen为什么在这里使用static_cast代替reinterpret_cast很重要?

甲提问指出

雷蒙德,相信C++的例子是不正确的,因为在派生类的基类子对象的位置 根据ISO C++ 2003标准是不确定的 (10-3,第168页),并且您假定 基类子对象始终处于开头。在C++中,C 的例子也不错,所以我会坚持下去。

雷蒙德说

[代码不会做这样的假设。这就是为什么 使用static_cast代替reinterpret_cast很重要。试一试:向OVERLAPPED添加一个虚拟的 方法(这样vtable就在前面)并观察 编译器的功能。 Raymond]

在阅读他的评论后我可以猜出。在示例中使用static_cast很好,但reinterpret_cast不是。因为reinterpret_cast不是转换vtable。我理解正确吗?
虽然,如果我在那里使用C-Style(不是reinterpret_cast),它是否也会出错?

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

+2

我对C++一点也不熟悉,但我的理解是,“重新解释强制转换”意味着在C中'*(destination_type *)&'意味着什么。推测“静态强制转换”实际上需要类关系帐户,并允许编译器进行非平凡的转换工作。 – 2012-02-04 05:51:41

回答

17

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

不,问题是reinterpret_cast完全遗忘了继承。它将简单地返回相同的地址。但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),它可能会出错吗?

A C样式转换被定义为成功以下的第一个:

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

正如你所看到的,static_castreinterpret_cast之前尝试过,所以在这种情况下,C样式转换也将做正确的事。


More info


不能保证。关于reinterpret_cast发生的情况几乎没有什么保证。我所知道的所有实现都将简单地给出相同的地址。

+0

是的,我的'convert vtable'是非常奇怪的句子。 btw,C风格的施法者是否也知道继承关系?也许它不是。但是我一直使用C风格的演员,即使我使用C++。我认为它在这个例子中运行得很好。这很奇怪。 – Benjamin 2012-02-04 06:10:04

+1

@Benjamin我添加了一个关于C风格演员的解释,以及为什么它在这种情况下工作。我会建议不要使用它们,因为它并不总是清楚选择哪个替代方案。一个C型的案例是一个非常钝的锤子。 – 2012-02-04 06:14:26

+0

当然我会按照你的建议,因为我现在明白了。谢谢。虽然您的C型脚轮的订单是否标准化? – Benjamin 2012-02-04 06:19:20

相关问题