2012-03-27 26 views
1

有人會好心解釋爲什麼下面的代碼工作,我已經測試了它在Visual Studio .NET 2008上,g ++上Cygwin和ideone.com。更重要的是,我想知道它是否有效。請注意,AB是不相關的類型。reinterpret_cast和無關的類型之間的虛擬

編輯:以下@ leftaroundabout的評論我做了如下改變我的代碼

#include <iostream> 
#include <cstdlib> 

class A 
{ 
public: 
    virtual void Bar() 
    { 
     std::cout << "A::Bar() -> " << this << std::endl; 
    } 

    virtual void Foo() 
    { 
     std::cout << "A::Foo() -> " << this << std::endl; 
    } 
}; 

class B 
{ 
public: 
    virtual void Foo() 
    { 
     std::cout << "B::Foo() -> " << this << std::endl; 
    } 
}; 

int main() 
{ 
    B* b = reinterpret_cast<B*>(new A); 
    b->Foo(); 
    return EXIT_SUCCESS; 
} 

程序輸出消息:

A::Bar() -> 0x9806008 

基本上第一個虛擬方法,無論叫的是什麼調用。

+1

我想它甚至在您將'A :: Foo'重命名爲'A :: Bar'並將所有其他事物保持原樣時「工作」? – leftaroundabout 2012-03-27 10:51:22

+0

http://www.google.com.ua/search?client=opera&rls=zh-CN&q=reinterpret_cast&sourceid=opera&ie=utf-8&oe=utf-8&channel=suggest – Alecs 2012-03-27 10:53:11

回答

3

它只是運氣好,沒有什麼標準說它應該工作 - 演員陣容是無效的。編譯器很可能在內存中完全按照相同的方式佈局這兩個類,但AFAIK沒有這樣的義務。

嘗試增加:在A

virtual void Bar() 
{ 
    std::cout << "A::Bar() -> " << this << std::endl; 
} 

之前Foo看看會發生什麼 - 沒準什麼時候運行b->Foo()Bar將被調用。

1

reinterpret_cast<>基本上關閉了任何類型的安全檢查,並告訴編譯器「不檢查這個,我知道我在做什麼。」

Microsoft's page on reinterpret_cast告訴它以及任何人;

一個的reinterpret_cast的結果不能安全地用於任何 不是被強制轉換回原來的類型等。其他用途在 最好,不便攜。

+1

雖然有些特殊情況下「reinterpret_cast」_is_實際上是標準的保證以某種特定的方式行事,例如'std :: complex z(1.,2。);''double * a = reinterpret_cast (&z);''std :: cout << a [0] <<「,」<< a [1];'將始終打印出「z」的實部和虛部 – leftaroundabout 2012-03-27 10:58:11

+0

@leftaroundabout不,它不需要閱讀標準中的5.2.10節 – 2012-03-27 11:03:16

+0

@AndreasBrinck:是的(C++ 11 26.4.4)。 – leftaroundabout 2012-03-27 11:39:40

0

這是無效的;解引用已轉換爲錯誤類型的指針會導致未定義的行爲。

在這種情況下,它似乎工作,因爲兩個對象都具有匹配的虛函數,並且編譯器恰好爲每個對象以相同的方式佈置虛擬分發元數據。雖然大多數編譯器可能會這樣做,但沒有指定,也不能依賴。

0

從標準5.2.10/7

一個指針,一個對象可以被顯式轉換爲一個指向不同type.65的 對象)除型 「指針在轉換一個rvalue到T1「到類型」指向T2的指針「(其中T1和T2是對象類型,並且其中T2的對齊要求不是 比T1更嚴格)並且回到其原始類型產生 原始指針值,這種指針轉換的結果是未指定的 。

這意味着是有保證的唯一的事情是,如果你投A到B,然後回到A你原來的指針回:

A* a = reinterpret_cast<A*>(reinterpret_cast<B*>(new A)); 
    a->Foo(); //Ok 

所有其他的用途是不確定的。