2017-04-23 53 views
2

我正在學習C++。 我想嘗試downcast一個接口類;儘管我已經學會了不好的編程設計可能會導致鑄造失敗。我可以使用static_cast來強制轉型嗎?

一些網站說:「使用dynamic_cast檢查向下鑄造的有效性」。但是,就我而言,我不需要檢查有效性,因爲我可以保證它是從基類向派生類的向下轉換。我在下面的示例代碼中嘗試了dynamic_cast和static_cast。他們運作良好。

當我可以保證它是一個有效的向下轉換時,我可以使用static_cast嗎?

示例代碼:

struct Parent_Interface { 
    virtual ~Parent_Interface() {}; 
    virtual void print(void) = 0; 
}; 

struct Child : public Parent_Interface { 
    virtual ~Child() {}; 
    void print(void) override { 
     std::cout << "Child::print()." << std::endl; 
    } 
}; 

void StaticDownCastToChild(Parent_Interface& parent_interface) { 
    auto& child0 = static_cast<Child&>(parent_interface); 
    std::cout << "StaticDownCastToChild : "; 
    child0.print(); 
} 

void DynamicDownCastToChild(Parent_Interface& parent_interface) { 
    auto& child0 = dynamic_cast<Child&>(parent_interface); 
    std::cout << "DynamicDownCastToChild : "; 
    child0.print(); 
} 

void test_static_cast_down_cast(void) { 
    Child c; 
    StaticDownCastToChild(c); 
    DynamicDownCastToChild(c); 
} 

執行test_static_cast_down_cast的輸出()。

StaticDownCastToChild : Child::print(). 
DynamicDownCastToChild : Child::print(). 
+0

使用'static_cast'是推薦的方式。只是關於*任何*演員。 –

+1

CRTP就是一個例子。 – chris

回答

3

有些網站說...

不要介意什麼一些網站說。標準(working draft)表示:

類型「CV1 B」,其中B是一個類型,可以轉換爲輸入「參照CV2 d」,其中d是從B來源的類的左值,如果cv2與cv1具有相同的cv資格,或者具有比cv1更高的cv資格。

此外,它包含一個例子是你所要求的幾乎相同:

struct B { }; 
struct D : public B { }; 
D d; 
B &br = d; 

static_cast<D&>(br);   // produces lvalue to the original d object 

所以我會說,是的,你可以做到這一點。

這樣的演員有很多用途。作爲一個例子,CRTP成語是你確切地知道什麼是派生類的類型的情況下,你不想檢查,如果中投有效通過使用dynamic_cast。你的情況可能是另一種情況(沒有原始代碼很難說)。

+0

謝謝你的回答。是的,我想通過一個接口類來創建一個類ContainerAny。我想通過使用接口可以提供的信息將容器元素轉換爲原始類,例如,element.classType();再一次非常感謝你。 – mora

+0

@mora我很樂意提供幫助。無論如何,有比「classType」方法更好的解決方案。我的兩分錢。 ;-) – skypjack

3

有些網站說, 「使用dynamic_cast的檢查下鑄造的有效性」。但是,就我而言,我不需要檢查有效性,因爲我可以保證它是從基類向派生類的向下轉換。

正確。

當我可以保證它是一個有效的向下轉換時,我可以使用static_cast嗎?

是。

其實,你應該,因爲它是「免費」的。 dynamic_cast通常涉及一些運行時間開銷。

但是,您可能希望將dynamic_cast放在assert的旁邊,這是很好的措施。請記住,這對您的發佈版本沒有任何影響,但如果出現可怕的錯誤,可能會在調試過程中爲您提供幫助。我職業生涯中最令人滿意的時刻有一段時間,意外地發生了一個良好的assert發射,導致了一個非常快速的錯誤修復過程;另一種選擇可能是幾個月的痛苦和猜測!

+0

謝謝你回答。我想創建一個ContainerAny類,它包含一些基類是接口類的類。我想使用來自接口的類型信息將容器的元素轉換爲原始類;例如element.type()。所以我希望我可以保證在第一次有效測試後它是有效的向下轉換。 – mora

+0

@mora:完美的使用案例。 –

0

當我可以保證它是一個有效的向下轉換時,我可以使用static_cast嗎?

是的,你可以。這就是說,情況下,您知道投將是有效的,但你不能指定更具體的類型(例如Child&)應該沒有拿出非常頻繁。我想不出你會使用Parent_Interface&代替Child&當你知道你總是通過後者的理由。

+1

常見的,當你有某種類型的實體註冊界面,你需要「撤消」基於一些非關鍵型的類型擦除。 –

+0

@Caleb:我儘量讓一類ContainerAny持有一些類,其基類是一個接口類。我想將容器的元素轉換爲原始類。 – mora

+0

叫它......;) –

相關問題