c++提供六種型別轉換符號。前兩種是c風格,稱為c風格強制轉換,(t)或者t(),他們的效果一樣。後面四種分別是:
負責將const型別轉換為非const型別,也可以反過來轉換。
通常非const型別會自動轉換成const型別,所以一般不需要使用const_cast進行轉換,但是如果有過載函式或者模板特化的話,還是有用的,請看下面的例子:
void
f(string& str)
void
f(string
const
& str)
int_tmain(
intargc, _tchar* argv)
將呼叫f(string const& str)版本。
使用const_cast強制將原本const型別轉換成非const型別是危險的行為。因為當你宣告乙個變數是const型別時,編譯器有可能將該常量放在rom中或者受到寫保護的ram頁中。當你又試圖轉換這種使用物理手段來保護的常量時,經常會表現為記憶體故障。所以,盡可能的避免這樣做,而且要意識到,一旦你讓乙個變數宣告為常量,你就應該永不回頭。
1)不能替代const_cast
c++標準規定static_cast不能用來將常量型別轉換為非常量型別,那要依賴於const_cast。
2)等價於建立臨時變數
static_cast可以用於達到類似於建立無具名臨時變數的效果,比如:
void
f(string
const
& str)
int_tmain(
intargc, _tchar* argv)
兩個對於f函式的呼叫都正確,並且標準規定了static_cast(「h」)和string(「h」)效果一樣。
3)支援所有隱式轉換
編譯器支援的隱式轉換操作都可以用static_cast完成。當較大的算術型別賦給較小的算術型別時,static_cast將關閉編譯器資料有可能丟失的警告。
4)比較安全
static_cast 在編譯時使用型別資訊執行轉換, 在轉換執行必要的檢測(諸如指標越界計算, 型別檢查). 其操作相對是安全的.
int n=9;
double d=static_cast < double > (n);
上面的例子中, 將乙個變數從 int 轉換到 double. 這些型別的二進位制表示式是不同的. 要將整數 9 轉換到 雙精度整數 9, static_cast 需要正確地為雙精度整數 d 補足位元位. 其結果為 9.0
因為它比較
安全,所以像下面我這樣亂來就不能被編譯器接受:
string str;
int* p=
static_cast
<
int*>(&str);
error c2440: 'static_cast' : cannot convert from 'std::string *__w64 ' to 'int *'
相比而言,c風格的強轉就是不安全的,因為下面的**編譯器允許:
string str;
int* p=(
int*)&str;
說static_cast只是比較安全,是因為這樣的**居然還是能通過:
intx=9;
string* p=static_cast(&x);
5)將void*轉換成t*
6)支援向下轉型
static_cast可以將指向基類的指標強制轉換成指向子類的指標。這不是dynamic_cast做的事情麼?它們有什麼區別呢?
簡單來說,static_cast速度更快,安全性更差,dynamic_cast效能較差,但是更加嚴格和安全。
dynamic_cast將基類型別物件的引用或者指標轉換為同一繼承層次中的派生型別的引用或指標。
dynamic_cast涉及執行時型別檢查,如果轉換指標失敗,將返回0,如果轉換引用失敗,將丟擲bad_cast型別的異常。
dynamic_cast首先檢查被請求的轉換是否有效,如果有效才進行實際的轉換。
dynamic_cast的效能是不高的,如果繼承的層次較深的話,影響更大,但這不是你轉而使用不太安全的static_cast的理由。
比較好的做法是避免向下轉型,基類提供更多的虛函式或者直接使用子類都是候選的辦法。
reinterpret_cast是強制編譯器接收程式設計師主觀認定的型別。它的行為不同於相對謹慎的static_cast, reinterpret_cast 僅僅是重新解釋了給出的物件的位元模型而沒有進行二進位制轉換,上面static_cast的例子修改一下:
int n=9;
double d=reinterpret_cast(n);
這次, 結果有所不同. 在進行計算以後, d 包含無用值. 這是因為 reinterpret_cast 僅僅是複製 n 的位元位到 d, 沒有進行必要的分析.所以小心使用reinterpret_cast,和c風格的強轉一樣的不安全。
不僅如此,reinterpret_cast的執行後果根據不同的編譯器上行為很可能不一樣,沒有可移植性。
作為乙個較安全的措施,我們可以這樣幹:
t1* p1=...;
t2* p2=reinterpret_cast(p1)
第二行換成如下**:
void* pv=p1;
t2* p2=static_cast(pv);
盡量少用reinterpret_cast,如果實在不行,試試用static_cast替代來降低風險提高移植性。
當你寫下任何一種轉換操作,編譯器都會在幕後寫出一些**,比如找到目標型別的型別資訊和記憶體布局,以便執行轉換。
假如你寫下如下c風格**:
class derived;
void gun(base* pb)
derived* pd=(derived*)pb;
你沒有#include 「derived.h」,而是通過前置宣告了derived型別,c風格轉換會讓你編譯通過,但是由於看不到derived.h檔案,所以編譯器會假定base和derived是兩個不相關的型別,不會對物件記憶體布局作必要的調整,結果是執行時可能莫名其妙崩潰。
而這種情況下如果你使用了c++風格的轉換,將會提示不能轉換的錯誤,便於保證程式的正確性。
c++風格的轉換操作符更容易搜尋。
七 3 型別轉換(strconv)
package main import fmt strconv func main else 字串 int if v,err strconv.atoi 1023 err nilelse 這裡 16指的是十六進製制轉換為十進位制,64表示int64型別 if v,err strconv.parsein...
21型別轉換
典型案例總結 靜態型別轉換,編譯的時c 編譯器會做型別檢查 基本型別能轉換 但是不能轉換指標型別,只要隱式型別轉換可以的地方都可以使用static cast。若不同型別之間,進行強制型別轉換,用reinterpret cast 進行重新解釋。一般性結論 總結 static cast 和reinter...
009 型別轉換
運算子兩邊的資料型別必須一致,且表示式的值 也是運算子兩邊的數的型別,不一致時,要先轉換,再運算。自動型別轉換 隱式型別轉換 將精度低的轉為精度高的資料,系統自動進行,不會造成資料精度丟失。前提 型別相容 double int double string 目標型別精度大於源型別 顯式型別轉換 強制轉...