2016-02-20 66 views
0

我只是想了解更多細節中的向下轉換,我明白這不可取,因爲它會導致未定義的運行時行爲。我們什麼時候真的需要使用羽絨服?在C++中使用reinterpret_cast向下轉換

還要考慮編碼代碼段和dynamic_cast返回的下投,但是當我使用reinterpret_cast時,它會正確輸出派生類函數,怎麼樣?只有在按值分配對象時,對象分片纔會到位,而不是通過引用或指針分配?

#include <iostream> 
using namespace std; 

class base 
{ 
    public: 
    void func1() 
    { 
     std::cout<<"\n Base Function"<<std::endl; 
    } 
    virtual ~base(){cout<<"\n Base Destructor"<<endl;} 
}; 

class derived:public base 
{ 
    public: 
    void func2() 
    { 
     std::cout<<"\n Derived Function"<<std::endl; 
    } 
}; 

int main() 
{ 

    base *ptr = dynamic_cast<base*>(new derived); // Up casting 
    if (ptr) 
    { 
     ptr->func1(); 
    } 
    else 
    { 
     cout<<"\n casting failed"<<endl; 
    } 

    derived *ptr1 = dynamic_cast<derived*>(new base); // Down casting 
    if (ptr1) 
    { 
     ptr1->func2(); 
    } 
    else 
    { 
     cout<<"\n ptr1 casting failed"<<endl; 
    } 

    return 0; 
} 
+3

'它正確地打印出派生類的功能,怎麼樣?'你描述的代碼會表現出未定義的行爲。 「似乎工作」是未定義行爲的一種可能表現形式。在你的具體例子中,'func2'實際上並不使用'this'指針,所以當所說的指針是垃圾時不會注意到。即使這似乎工作:'derived * p = NULL; p-> func2();' –

+2

'派生* ptr1 = dynamic_cast (新基地);'是內存泄漏,'ptr1'結果爲空的事實應該向您清楚演員陣容是無效的。 '派生* ptr1 = reinterpret_cast (新基地);'只會導致未定義的行爲。 – user657267

+0

@Igor:UB來自哪裏? –

回答

2

自下而上不會導致未定義的行爲。如果你有一個指針或引用base,你可以使用dynamic_cast,並確保它只有在它是一個派生的時候纔會起作用。如果它不是派生的,你將得到一個nullptr或一個異常(當投射一個參考時)。一切都將在運行時檢查。

如果您已經知道您的基指針是派生的,則可以使用static_cast來代替。但是,不會執行檢查,以便您可以導致基本指針的未定義行爲不是派生的。

reinterpret_cast不應該用於向下轉換。與static_cast一樣,不會執行運行時檢查,也不會執行編譯時檢查。您可能會意外投射繼承樹(例如從基地到other_base)。 對於單繼承的情況,reinterpret_cast將像static_cast一樣工作,但是當使用多重繼承時,reinterpret_cast將不會修改指向對象內部正確基址的指針,並且您有未定義的行爲。

當你可以使用static_cast代替時,我會建議遠離reinterpret_cast。