何時應該使用static_cast,dynamic_cast,const_cast和reinterpret_cast?

的正確用法是: windows

  • static_cast
  • dynamic_cast
  • const_cast
  • reinterpret_cast
  • C樣式轉換(type)value
  • 函數樣式轉換type(value)

如何決定在特定狀況下使用哪一個? 安全


#1樓

(上面已經給出了不少理論和概念上的解釋) 函數

下面是當我使用static_castdynamic_castconst_castreinterpret_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);
}

#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);

#3樓

這能回答您的問題嗎?

我歷來沒有使用過reinterpret_cast ,而且想知道是否遇到須要它的狀況不會引發不良設計的味道。 在我處理dynamic_cast的代碼庫中,使用了不少代碼。 與static_cast的區別在於, dynamic_cast會進行運行時檢查,這可能(更安全)或可能(更多開銷)不是您想要的(請參閱msdn )。


#4樓

使用dynamic_cast在繼承層次結構中轉換指針/引用。

使用static_cast進行普通類型轉換。

使用reinterpret_cast對位模式進行低級從新解釋。 使用時要格外當心。

使用const_cast放棄const/volatile 。 除非您使用const不正確的API,不然請避免這種狀況。


#5樓

static_cast是您應該嘗試使用的第一個演員表。 它的做用相似於類型之間的隱式轉換(例如intfloat或指向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_castvolatile上也相似地工做,儘管這種狀況不太常見。


dynamic_cast僅用於處理多態。 您能夠將任何多態類型的指針或引用強制轉換爲任何其餘類類型(多態類型至少具備一個聲明或繼承的虛函數)。 您不只能夠向下投射,還可使用它–您能夠側向投射,甚至向上投射另外一個鏈。 dynamic_cast將查找所需的對象,並在可能的狀況下將其返回。 若是不能,則在使用指針的狀況下將返回nullptr ,在使用引用的狀況下將返回std::bad_cast

dynamic_cast有一些限制。 若是繼承層次結構中有多個相同類型的對象(所謂的「可怕的鑽石」),而且您沒有使用virtual繼承,則該方法將無效。 它也只能進行公共繼承-它將始終沒法經過protected繼承或private繼承。 可是,這不多有問題,由於這種繼承形式不多。


reinterpret_cast是最危險的強制類型轉換,應謹慎使用。 它將一種類型直接轉換爲另外一種類型-例如將值從一個指針轉換爲另外一種指針,或將指針存儲在int或其餘各類討厭的東西中。 在很大程度上,只有保證你獲得reinterpret_cast是,一般,若是你把結果返回到原來的類型,你會獲得的值徹底相同( 若是中間型比原來的類型更小)。 reinterpret_cast也沒法完成許多轉換。 它主要用於特別奇怪的轉換和位操做,例如將原始數據流轉換爲實際數據,或將數據存儲在指向對齊數據的指針的低位。


C樣式轉換和函數樣式轉換分別是使用(type)objecttype(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樣式強制轉換的另外一個緣由。

相關文章
相關標籤/搜索