這個問題是關於哪個C++ style cast應該用來進行這種轉換。我知道C風格的演員可以實現這一點。什麼類型的演員從父母到孩子?
對於以下class
結構:
class Foo {};
class Bar : public Foo {};
說我給出:Foo* ptr;
,我想將它轉換爲Bar*
投的類型,我應該使用哪個?好像我必須用dynamic_cast
,因爲它是:
用於多態類型
我想避免dynamic_cast
,因爲它是一個運行時投的轉換。
這個問題是關於哪個C++ style cast應該用來進行這種轉換。我知道C風格的演員可以實現這一點。什麼類型的演員從父母到孩子?
對於以下class
結構:
class Foo {};
class Bar : public Foo {};
說我給出:Foo* ptr;
,我想將它轉換爲Bar*
投的類型,我應該使用哪個?好像我必須用dynamic_cast
,因爲它是:
用於多態類型
我想避免dynamic_cast
,因爲它是一個運行時投的轉換。
你是正確的,dynamic_cast
通常是最適合這種情況。但是,如果您知道指針實際上指向派生類的對象,則可以使用static_cast
進行轉換。如果你錯了,指針是而不是派生類,你會得到未定義的行爲。
我確實知道'ptr'是一個'Bar *'。所以我假設你在這個列表中引用了第二種類型的轉換:http://en.cppreference.com/w/cpp/language/static_cast#Explanation –
@JonathanMee是的,這就是我正在談論的 - 儘管我認爲基類不是非虛擬化的必要條件。 –
你敢挑戰http://en.cppreference.com的智慧O.O –
static_cast
只要您確定您投射的對象真的是您期望的類型,就可以正常工作。根據你給出的例子,看起來你確定。
爲了清楚起見:
我想避免
dynamic_cast
,因爲它是一個運行時施放。
好了,你有一個運行時類型(給出一個靜態類型的參考基礎類,你不能一般知道動態類型的對象),所以運行時投是唯一完全安全的選擇。
如果您認爲自己的物體確實是Bar
,但被誤認爲dynamic_cast<Bar*>
會給您一個nullptr
或dynamic_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爲了節省時間名義你的代碼文件之前是過早優化的定義。
您的代碼不正確,因爲'dynamic_cast'只能用於具有至少一個虛擬功能的類。 –
「你的基類對象的靜態類型真的是Bar」 - 這不是靜態類型*的意思。 –
好點,這是一個不幸的表述。 – Useless
這是你應該避免的事情,做這些事情是設計問題的標誌。如果你認爲你真的需要這個,你可以比較類的類型,如果它匹配,你可以static_cast指針...它的速度比dynamic_cast快,但如果你不知道確切的目的地類,它將不起作用。 – Melkon
@Melkon如何檢查typeid比dynamic_cast更快?你看到了哪個編譯器和設置? –
@MarkRansom:typeid檢查不會遍歷類層次結構。 – Melkon