2015-09-10 87 views
3

這個問題是關於哪個C++ style cast應該用來進行這種轉換。我知道C風格的演員可以實現這一點。什麼類型的演員從父母到孩子?

對於以下class結構:

class Foo {}; 

class Bar : public Foo {}; 

說我給出:Foo* ptr;,我想將它轉換爲Bar*投的類型,我應該使用哪個?好像我必須用dynamic_cast,因爲它是:

用於多態類型

我想避免dynamic_cast,因爲它是一個運行時投的轉換。

+0

這是你應該避免的事情,做這些事情是設計問題的標誌。如果你認爲你真的需要這個,你可以比較類的類型,如果它匹配,你可以static_cast指針...它的速度比dynamic_cast快,但如果你不知道確切的目的地類,它將不起作用。 – Melkon

+0

@Melkon如何檢查typeid比dynamic_cast更快?你看到了哪個編譯器和設置? –

+1

@MarkRansom:typeid檢查不會遍歷類層次結構。 – Melkon

回答

6

你是正確的,dynamic_cast通常是最適合這種情況。但是,如果您知道指針實際上指向派生類的對象,則可以使用static_cast進行轉換。如果你錯了,指針是而不是派生類,你會得到未定義的行爲。

+0

我確實知道'ptr'是一個'Bar *'。所以我假設你在這個列表中引用了第二種類型的轉換:http://en.cppreference.com/w/cpp/language/static_cast#Explanation –

+0

@JonathanMee是的,這就是我正在談論的 - 儘管我認爲基類不是非虛擬化的必要條件。 –

+0

你敢挑戰http://en.cppreference.com的智慧O.O –

1

static_cast只要您確定您投射的對象真的是您期望的類型,就可以正常工作。根據你給出的例子,看起來你確定。

1

爲了清楚起見:

我想避免dynamic_cast,因爲它是一個運行時施放。

好了,你有一個運行時類型(給出一個靜態類型的參考基礎類,你不能一般知道動態類型的對象),所以運行時投是唯一完全安全的選擇。

如果您認爲自己的物體確實是Bar,但被誤認爲dynamic_cast<Bar*>會給您一個nullptrdynamic_cast<Bar&>會拋出異常。無論哪種方式,您都有機會在運行時處理運行時錯誤。正如M.M指出的那樣,只有當您的基類具有或繼承至少一個虛擬方法時纔可用。

現在如果,一個偶然的機會,你可以靜態一定的動態類型的對象的真正Bar,您可以使用static_cast。但是,如果你錯了,你有未定義的行爲,沒有機會檢測或處理錯誤。

例如。

struct Foo { virtual ~Foo(){} }; 
struct Bar : public Foo {}; 

// safe, may return nullptr 
Bar* safe_ptr_cast(Foo *f) { return dynamic_cast<Bar*>(f); } 

// safe, may throw but you can catch it 
Bar& safe_ref_cast(Foo &f) { return dynamic_cast<Bar&>(f); } 

// unsafe - if you're wrong, you just broke everything 
Bar* unsafe_ptr_cast(Foo *f) { return static_cast<Bar*>(f); } 

順便說一句,如果與運行時間投你的問題是性能,冒着UB爲了節省時間名義你的代碼文件之前是過早優化的定義。

+1

您的代碼不正確,因爲'dynamic_cast'只能用於具有至少一個虛擬功能的類。 –

+0

「你的基類對象的靜態類型真的是Bar」 - 這不是靜態類型*的意思。 –

+0

好點,這是一個不幸的表述。 – Useless