2012-07-16 62 views
11

Scott Meyer在他的書Effective C++dynamic_cast是用來執行安全的強制轉換或繼承層次結構。也就是說,您可以使用dynamic_cast將指針或對基類對象的引用轉換爲指向派生或同級基類對象的指針或引用,以便您可以確定轉換是否成功。如何使用dynamic_cast運算符來識別失敗的轉換?

失敗轉換由空指針(轉換指針時)或異常(轉換引用時)表示。

我想得到兩個代碼片段,顯示在鑄造指針失敗的情況下可以指示鑄造參考。

+4

您是否要求提供測試指針是否爲空以及捕獲異常的代碼的代碼示例? – 2012-07-16 18:18:28

+0

不,我不明白斯科特提到演員如何失敗。代碼片段肯定會有所幫助。 – 2012-07-16 18:21:25

+1

http://en.wikipedia.org/wiki/Dynamic_cast – 2012-07-16 18:22:08

回答

21

對於三分球,這是一個簡單的空檢查:

A* a = new A(); 
B* b = dynamic_cast<B*>(a); 

if (b == NULL) 
{ 
    // Cast failed 
} 

對於引用,你可以捕捉:

try { 
    SomeType &item = dynamic_cast<SomeType&>(obj); 
} 
catch(const std::bad_cast& e) { 
    // Cast failed 
} 
+0

@LinuxPenseur該檢查假設「a」具有有效值。你必須首先檢查(分配)。 dynamic_cast檢查是檢查A是否可以安全地轉換爲「B」 - 所以檢查是針對'NULL'的'b' - 即:b是null並且a不爲null。 – 2012-07-16 18:28:51

+0

@ReedCopsey:什麼是我的'安全演員'。在哪種情況下可以變成NULL? – 2012-07-16 18:30:59

+1

當一個類是多態的時候使用'dynamic_cast'(具有'virtual'函數),它執行運行時檢查,返回一個'NULL'指針。通過使用'dynamic_cast',您可以告訴它在嘗試各種類型的轉換時完成您想要的功能而不是C-Style轉換。當您不知道要轉換的對象時,也會使用'dynamic_cast',而不是'static_cast'用於非多聚類,並且轉換中的兩種類型都是已知的 – 2012-07-16 18:31:44

3

基礎上OP的評論(」我不知道如何強制轉換可能失敗,因爲「),這裏真正的問題是這樣的:」dynamic_cast怎麼會失敗?「

當目標類型與對象的動態類型不匹配時,它會失敗的時間。對於一個簡單的例子:

struct A { 
    virtual ~A() {} 
}; 

class B : public A {}; 

int main() { 
    A *a = new A; 

    B *b = dynamic_cast<B *>(a); // should fail 
    if (b == NULL) 
     std::cout << "First cast failed.\n"; 

    A *c = new B; 
    b = dynamic_cast<B *>(c);  // should succeed 
    if (b == NULL) 
     std::cout << "Second cast failed.\n"; 
    return 0; 
} 

這裏雖然a所能指向B類型的對象,它實際上確實指向A類型的對象。當我們嘗試執行dynamic_cast以使其指向B時,失敗。在第二次嘗試中,我們再次有一個指針,不僅,而且指向B類型的對象。既然如此,dynamic_cast到B *就成功了。

的基本情況不改變(多)爲參考的情況下,只是abc成爲引用,而不是指針,我們通過捕獲異常注意故障(其中@ReedCopsey已經證明不夠好,我不認爲我有什麼新的補充)。

3

下面是一個完整的示例,顯示dynamic_cast可能無法生成指針。

class A 
{ 
public: 
    virtual void Foo(); 
}; 

class B: public A 
{ 
}; 

class C: public A 
{ 
}; 

void test() 
{ 
    A a; 
    B b; 
    A* pA = &b; 
    B* pB = dynamic_cast<B*>(pA); // this works OK, returns the expected pointer 
    C* pC = dynamic_cast<C*>(pA); // this returns NULL because B isn't a C 
} 

在你試圖施放該不是如此直截了當地創建指向現實世界中,或許他們來自vector例如。