2012-11-11 99 views
10

我正在瀏覽CodeProject中的一些代碼,並且遇到了下面的C++代碼轉換代碼。C++ Cast的實現

template <class OutputClass, class InputClass> 
union horrible_union{ 
    OutputClass out; 
    InputClass in; 
}; 
template <class OutputClass, class InputClass> 
inline OutputClass horrible_cast(const InputClass input){ 
    horrible_union<OutputClass, InputClass> u; 
    u.in = input; 
    return u.out; 
} 

爲什麼演員執行上述方式。爲什麼我們不能做一個手動演員。有人能舉出一個正常演員陣容何時無法工作的例子嗎?

+4

設置其他成員後訪問工會的成員是未定義的行爲,所以任何事情都比這種'horrible_union'方法更好。 –

+0

也許這就是爲什麼它被命名爲可怕的演員。這基本上是爲了實現一些編譯器特定的行爲。 – KodeWarrior

回答

9

這種方法基本上可以讓你擺脫任何強制轉換,儘管它依賴於未定義的行爲。

在不相關類型之間進行投射時,正常投射會投訴,但這不會。

struct A{}; 
struct B{}; 

template <class OutputClass, class InputClass> 
union horrible_union{ 
    OutputClass out; 
    InputClass in; 
}; 
template <class OutputClass, class InputClass> 
inline OutputClass horrible_cast(const InputClass input){ 
    horrible_union<OutputClass, InputClass> u; 
    u.in = input; 
    return u.out; 
} 

int main() 
{ 
    A a; 
    B b; 
    a = horrible_cast<A,B>(b); //this compiles 
    a = reinterpret_cast<A>(b); //this doesn't 
} 

底線:這太可怕了,不要這樣做。

+1

如果您正在使用特定的體系結構並使用特定的編譯器(對於某些嵌入式系統),則可能是僅在該體系結構上纔有意義的類型轉換的有效方法。但我同意,這仍然很危險。 – bitmask

2

以這種方式使用聯合通常大致等同於指針的硬reinterpret_cast。但是,這不會複製對象,您的示例(即使是使用RVO也是兩次;事實上,使用const InputClass& input作爲參數會更有效)。所以你可以直接操作它的結果而不用改變原來的對象。

這對於...... hm有什麼用處。我認爲沒有什麼非常好的用例,總是應該避免未經檢查的轉換,並且正如David Hammen所說的那樣,實際上它完全沒有定義(儘管如果使用「正確」的話,它通常會起作用)。

+0

也許他們的商店有一個針對'reinterpret_cast'的政策,但不是這個漏洞。 – Barmar

+0

在這種情況下,使用它會更加可怕:'reinterpret_cast'是危險的,但這個更糟糕。 – leftaroundabout

+0

就我個人而言,我更喜歡看到'reinterpret_cast'(也許必須遵循放棄之後,如果有規則反對它)隱藏演員像這樣。 –