2012-02-04 37 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

相關問題