的正確用法是: windows
static_cast
dynamic_cast
const_cast
reinterpret_cast
(type)value
type(value)
如何決定在特定狀況下使用哪一個? 安全
(上面已經給出了不少理論和概念上的解釋) 函數
下面是當我使用static_cast , dynamic_cast , const_cast , reinterpret_cast時的一些實際示例 。 ui
(也參考此以理解說明: http : //www.cplusplus.com/doc/tutorial/typecasting/ ) spa
static_cast: debug
OnEventData(void* pData) { ...... // pData is a void* pData, // EventData is a structure e.g. // typedef struct _EventData { // std::string id; // std:: string remote_id; // } EventData; // On Some Situation a void pointer *pData // has been static_casted as // EventData* pointer EventData *evtdata = static_cast<EventData*>(pData); ..... }
dynamic_cast: 設計
void DebugLog::OnMessage(Message *msg) { static DebugMsgData *debug; static XYZMsgData *xyz; if(debug = dynamic_cast<DebugMsgData*>(msg->pdata)){ // debug message } else if(xyz = dynamic_cast<XYZMsgData*>(msg->pdata)){ // xyz message } else/* if( ... )*/{ // ... } }
const_cast: 指針
// *Passwd declared as a const const unsigned char *Passwd // on some situation it require to remove its constness const_cast<unsigned char*>(Passwd)
reinterpret_cast: code
typedef unsigned short uint16; // Read Bytes returns that 2 bytes got read. bool ByteBuffer::ReadUInt16(uint16& val) { return ReadBytes(reinterpret_cast<char*>(&val), 2); }
除了到目前爲止的其餘答案以外,這是一個顯而易見的示例,其中static_cast
不足,所以須要reinterpret_cast
。 假設有一個函數,該函數在輸出參數中返回指向不一樣類(不共享公共基類)的對象的指針。 此類函數的真實示例是CoCreateInstance()
(請參閱最後一個參數,其實是void**
)。 假設您今後函數請求特定的對象類,所以您預先知道了指針的類型(一般對COM對象執行此操做)。 在這種狀況下,您沒法使用static_cast
將指針轉換爲void**
:您須要reinterpret_cast<void**>(&yourPointer)
。 對象
在代碼中:
#include <windows.h> #include <netfw.h> ..... INetFwPolicy2* pNetFwPolicy2 = nullptr; HRESULT hr = CoCreateInstance(__uuidof(NetFwPolicy2), nullptr, CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2), //static_cast<void**>(&pNetFwPolicy2) would give a compile error reinterpret_cast<void**>(&pNetFwPolicy2) );
可是, static_cast
適用於簡單的指針(而不是指向指針的指針),所以能夠經過如下方式重寫以上代碼,以免reinterpret_cast
(以額外的變量爲代價):
#include <windows.h> #include <netfw.h> ..... INetFwPolicy2* pNetFwPolicy2 = nullptr; void* tmp = nullptr; HRESULT hr = CoCreateInstance(__uuidof(NetFwPolicy2), nullptr, CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2), &tmp ); pNetFwPolicy2 = static_cast<INetFwPolicy2*>(tmp);
這能回答您的問題嗎?
我歷來沒有使用過reinterpret_cast
,而且想知道是否遇到須要它的狀況不會引發不良設計的味道。 在我處理dynamic_cast
的代碼庫中,使用了不少代碼。 與static_cast
的區別在於, dynamic_cast
會進行運行時檢查,這可能(更安全)或可能(更多開銷)不是您想要的(請參閱msdn )。
使用dynamic_cast
在繼承層次結構中轉換指針/引用。
使用static_cast
進行普通類型轉換。
使用reinterpret_cast
對位模式進行低級從新解釋。 使用時要格外當心。
使用const_cast
放棄const/volatile
。 除非您使用const不正確的API,不然請避免這種狀況。
static_cast
是您應該嘗試使用的第一個演員表。 它的做用相似於類型之間的隱式轉換(例如int
到float
或指向void*
指針),它還能夠調用顯式轉換函數(或隱式函數)。 在許多狀況下,無需明確聲明static_cast
,但必須注意, T(something)
語法與(T)something
等效,應避免使用(稍後會詳細介紹)。 T(something, something_else)
是安全的,而且保證能夠調用構造函數。
static_cast
也能夠經過繼承層次結構進行static_cast
。 向上(朝向基類)進行強制轉換時沒有必要,可是向下轉換時只要不經過virtual
繼承進行轉換就可使用。 可是,它不進行檢查,而且將層次結構static_cast
下降爲實際上不是對象類型的類型是未定義的行爲。
const_cast
可用於將const
刪除或添加到變量; 沒有其餘C ++強制轉換可以將其刪除(甚至不能reinterpret_cast
)。 重要的是要注意,僅當原始變量爲const
,才能夠修改之前的const
值; 若是使用它來使const
脫離對未使用const
聲明的內容的引用,則這是安全的。 例如,這在基於const
重載成員函數時頗有用。 它還能夠用於向對象添加const
,例如調用成員函數重載。
const_cast
在volatile
上也相似地工做,儘管這種狀況不太常見。
dynamic_cast
僅用於處理多態。 您能夠將任何多態類型的指針或引用強制轉換爲任何其餘類類型(多態類型至少具備一個聲明或繼承的虛函數)。 您不只能夠向下投射,還可使用它–您能夠側向投射,甚至向上投射另外一個鏈。 dynamic_cast
將查找所需的對象,並在可能的狀況下將其返回。 若是不能,則在使用指針的狀況下將返回nullptr
,在使用引用的狀況下將返回std::bad_cast
。
dynamic_cast
有一些限制。 若是繼承層次結構中有多個相同類型的對象(所謂的「可怕的鑽石」),而且您沒有使用virtual
繼承,則該方法將無效。 它也只能進行公共繼承-它將始終沒法經過protected
繼承或private
繼承。 可是,這不多有問題,由於這種繼承形式不多。
reinterpret_cast
是最危險的強制類型轉換,應謹慎使用。 它將一種類型直接轉換爲另外一種類型-例如將值從一個指針轉換爲另外一種指針,或將指針存儲在int
或其餘各類討厭的東西中。 在很大程度上,只有保證你獲得reinterpret_cast
是,一般,若是你把結果返回到原來的類型,你會獲得的值徹底相同( 但若是中間型比原來的類型更小)。 reinterpret_cast
也沒法完成許多轉換。 它主要用於特別奇怪的轉換和位操做,例如將原始數據流轉換爲實際數據,或將數據存儲在指向對齊數據的指針的低位。
C樣式轉換和函數樣式轉換分別是使用(type)object
或type(object)
進行的轉換,而且在功能上等效。 它們被定義爲如下成功的第一個:
const_cast
static_cast
(儘管忽略訪問限制) static_cast
(請參見上文),而後是const_cast
reinterpret_cast
reinterpret_cast
,而後是const_cast
所以,在某些狀況下,它能夠替代其餘類型的轉換,可是因爲有能力降級到reinterpret_cast
,所以很是危險,而且在須要顯式轉換時應首選後者,除非您肯定static_cast
將成功或reinterpret_cast
將失敗。 即便這樣,也能夠考慮使用更長,更明確的選項。
C樣式強制轉換在執行static_cast
時也會忽略訪問控制,這意味着它們具備執行其餘強制轉換沒法執行的操做的能力。 可是,這主要是一種爭執,在我看來,這是避免使用C樣式強制轉換的另外一個緣由。