2017-01-12 51 views
0
#include <iostream> 

class Base { 
}; 

class Derived : public Base { 
}; 

int main() { 
    Base* bptr = new Derived(); 

    Derived* dptr = static_cast<Derived*>(bptr); 

    std::cout << dptr << std::endl; 
} 

在上面的代碼中,我應該使用dynamic_cast,但我錯誤地使用了 static_cast。因爲編譯器無法確定我們正在做 正確投射,所以static_cast不應該被使用,而 向下投射。C++ static_cast vs dynamic_cast

爲什麼不是編譯錯誤?我正在使用gcc 4.9.2。你們 認爲這是編譯器中的錯誤,還是C++標準允許這樣的代碼?

編輯:謝謝你的迴應。實際上,上面的基類是多態的 ,即它具有虛函數,但在本例中我省略了它們。我應該 在基地虛擬析構函數中拋出,以明確它是 是多態 - 我的不好。

+5

您可以從'Base *'的'static_cast' 'Derived *',但你是正確的,它不會執行任何類型檢查。它仍然很有用,但如果通過其他方式知道該指針確實指向了「Dervied」對象。如果'Base *'實際上沒有指向Derived *,那麼由'static_cast'產生的Derived *'的任何解引用都會引發未定義的行爲。 –

+0

在所有現實中,這完全是* static_cast是什麼;畢竟,轉向基類指針/引用是隱式完成的。 –

回答

1

static_cast <new_type> (expression)

如果new_type是一個指針或引用某些類d和 expression類型是指針或引用其非虛擬基B, 的static_cast執行向下轉換。是形成不良的這個垂頭喪氣如果B是 曖昧,交通不便,或虛擬基(或虛擬基底的基底)D.這樣的static_cast的 使得沒有運行時檢查,以確保 對象的運行時類型實際上是d,並且可以只有在 這個前提條件由其他方式保證時才能安全使用,例如 實現靜態多態性。安全向下可以通過 dynamic_cast完成。

Source(說明項目2)

4

在上面的代碼中,我應該使用dynamic_cast但現在用static_cast不正確。 static_cast不應該在向下轉換時使用,因爲編譯器無法確定我們是否正確轉換。

具有諷刺意味的是,dynamic_cast實際上是這裏不合格的陣容,因爲你的類型不是多態的。

這就是說,static_cast當然可以用來垂頭喪氣。編譯器無法進行類型檢查是正確的,但在很多情況下,您有一個Base*並知道它指向一個Derived*,因此您可以手動執行該類型檢查。一個非常常見的情況是CRTP:

template <class Derived> 
class Base { 
    Derived& self() { return *static_cast<Derived*>(this); } 
    // ... 
}; 


class Foo : Base<Foo> { ... }; 

Base<T>總是一個T,使垂頭喪氣是安全的。

static_cast優於dynamic_cast的優點是static_cast是免費的,但dynamic_cast是昂貴的。 C++的口頭禪並不支付你不需要的東西。

0

你是完全正確的使用static_cast。你是對的,編譯器可以在一般情況下不知道轉換是否正確,但static_cast恰恰就是這種情況。

此處不能使用dynamic_cast,因爲該類型是針對多態類(具有虛擬成員函數的類)。這些類攜帶運行時信息;該信息允許代碼在指向的對象的實際類型中選擇該函數的正確實現。對象中的這個類型信息可以被cast函數用來確定類型轉換是否可能,然後確實正確執行轉換(這對於多重和虛擬繼承來說可能很棘手)。

沒有虛函數的類(如您的示例類)不包含此運行時信息,並且不能使用dynamic_cast轉換爲更多派生類型。 (它仍然可以用於投射到相同類型或基類,即它可以用於實際上不需要投射的轉換。)

相關問題