static_cast 任何具有明確定義的類型轉換,只要不包含底層const,都可以使用static_cast。例如: int i = 3, j = 2; double slope = static_cast<double>(i) / j; static_cast還可以用於把void*轉換成別的類型 ...
static_cast 任何具有明確定義的類型轉換,只要不包含底層const,都可以使用static_cast。例如: int i = 3, j = 2; double slope = static_cast<double>(i) / j; static_cast還可以用於把void*轉換成別的類型的指針: void* p = &slope; double *dp = static_cast<double*>(p); 可以認為static_cast和C中的強制類型轉換類似,例如,用C中的強制類型轉換是這樣的: double slope = ((double)i) / j; static_cast還可以用於處理explicit構造函數。例如: class A { public: explicit A(int n):n(n){} int getN(){return n;} private: int n; }; int getN(A a) { return a.getN(); } 這種情況下,寫 getN(12); 是不合法的。可以這麼寫: getN(static_cast<A>(12)); const_cast 只能用於改變底層const。例如,將常量對象轉換成非常量對象(cast away the const)。例如: const char *pc; char *p = const_cast<char*>(pc); 當然,如果pc所指向的對象本來就是一個常量,上述代碼也可以通過編譯,但是執行結果是未定義行為。 註意:只有const_cast能改變表達式的常量屬性,用別的方式改變表達式的常量屬性會引發編譯錯誤。 const_cast常用在函數重載中: 例如,有一個函數,接受const類型的引用作為參數,返回一個const類型的引用: const string &shorter(const string &s1, const string &s2) { return s1.size() <= s2.size() ? s1 : s2; } 如果我們把兩個非常量的string類型的變數作為實參傳給這個函數,那麼返回值依然是const string &。所以我們需要重載這個函數,當它的實參不是常量時,返回一個非常量的引用: string &shorter(string &s1, string &s2) { return s1.size() <= s2.size() ? s1 : s2; } 這樣寫就解決了問題。但是,為了避免兩個重載函數的函數體中的重覆代碼,可以把第二個函數改成: string &shorter(string &s1, string &s2) { auto &r = shorter(const_cast<const string&>(s1), const_cast<const string&>(s2)); return const_cast<string&>(r); } 註意:1、函數體的第一行將實參強制轉換成對const的引用,所以,第一行中shorter的返回值r是綁定在string&上的。因此函數體的第二行將r強制轉換成string&是安全的;2、要用non-const版本的函數去調用const版本的函數,千萬不要反過來。 reinterpret_cast 在記憶體位的層次上進行轉換,用於各種胡來。例如: char *p; int n = reinterpret_cast<int>(p); dynamic_cast 用於在一個派生體系中進行動態類型轉換。一般是將指向基類的指針(或引用)轉換為指向派生類的指針(或引用) 當轉換失敗時(即,被轉換的指針(或引用)並不是指向派生類的指針(或引用)): 1、轉換對象是指針:返回一個值為0的指針 2、轉換對象是引用:拋出異常std::bad_cast,這個異常定義在typeinfo標準庫頭文件中。 註意:dynamic_cast,在多數編譯器上,都比其它類型轉換要慢。 補充說明: 把非const變數轉成const,可以使用static_cast,把const轉成非const,只能使用const_cast。 在重載中使用const_cast是合理的。除此之外的強制類型轉換(static_cast和dynamic_cast)都要慎用。reinterpret_cast尤其是用於扯淡的。