1. 顯式轉換
顯式轉換也稱爲強制類型轉換(cast),包括如下列名字命名的強制類型轉換操做符:
static_cast、dynamic_cast、const_cast、reinterpret_cast。
雖然有時候確實須要強制類型轉換,可是它們本質上是很是危險的。
2. 什麼時候須要強制類型轉換
由於要覆蓋一般的標準轉換,因此需顯式使用強制類型轉換。下面的複合賦值:
double dval;
int ival;
ival = ival * dval;
爲了與dval作乘法操做,需將ival轉換爲double型,而後將乘法操做的double型結果截尾爲int型,再同賦值給ival。爲了去掉將ival轉換爲dobule型這個沒必要要的轉換,可經過以下操做強制將dval轉換爲
int型:
ival *= static_cast<int>(dval); // converts dval to int
顯式使用強制類型轉換的另外一個緣由是:可能存在多種轉換時,須要選擇一種特定的類型轉換。程序員
3. 命名的強制類型轉換
命名的強制類型轉換符號的通常形式以下:
cast-name<type>(expression);
其中cast-name爲static_cast、dynamic_cast、const_cast和reinterpret_cast之一,type爲轉換的目標類型,而expression則是被強制轉換的值。強制轉換的類型指定了在expression上執行某種特定類型的轉換。
dynamic_cast
dynamic_cast支持運行時識別指針或引用所指向的對象。如將基類對象轉換爲子類對象。express
const_cast
const_cast,顧名思義,將轉換掉表達式的const性質。例如,假設有函數string_copy,只有惟一的參數,爲char*類型,咱們對該函數只讀不寫。在訪問該函數時,最好的選擇是修改它的接受const char*類型的參數。若是不行,可經過const_cast用一個const值調用string_copy函數:
const char *pc_str;
char *pc = string_copy( const_cast<char*>(pc_str) );
只有使用const_cast才能將const性質轉換掉。在這種狀況下,試圖使用其餘三種形式的強制轉換都會致使編譯時的錯誤。相似地,除了添加或刪除const特性,用const_cast符來執行其餘類型轉換,都會引發編譯錯誤。
static_cast
編譯器隱式執行的任何類型轉換均可以由static_cast顯式完成:
double d = 97.0;
// cast specified to indicate that the conversion is intentional
char ch = static_cast<char>(d);
當須要將一個較大的算術類型賦值給較小的類型時,使用強制轉換很是有用。此時,強制類型轉換告訴程序的讀者和編譯器:
咱們知道關心潛在的精度損失。對於從一個較大的算術類型到一個較小類型的,賦值,編譯器一般會產生警告。當咱們顯式地提供強制類型轉換時,警告信息就會關閉。
若是編譯器不提供自動轉換。使用static_cast來執行類型轉換也是頗有用的。例如,下面的程序使用static_csat找回存放在
void*指針中的值(第4.2.2節):
void *p = &d; //ok: address of any data object can be stored in a void*
//ok, converts void* back to the original pointer type
double *dp = static_cast<double*>(p);
可經過static_cast將存放在void*中的指針值強制轉換爲原來的指針類型,此時咱們就確保保持指針值。也就是說,強制轉換的結果與原來的地址值相等。
reinterpret_cast
reinterpret_cast一般爲操做數的位模式提供提供較低層次的從新解釋。
reinterpret_cast本質上依賴於機器。爲了安全地使用reinterpret_cast,要求程序員徹底理解所涉及的數據類型,以及編譯器實現強制類型轉換的細節。
例如,對於下面的強制轉換:
int *ip;
char *pc = reinterpret_cast<char*>(ip);
程序員必須永遠記得 pc 所指向的真實對象實際上是 int 型,而並不是字符數組。任何假設 pc 是普通字符指針的應用,都有可能帶來有趣的運行時錯誤。例如,下面語句用 pc 來初始化一個 string 對象:
string str(pc);
它可能會引發運行時的怪異行爲。
用 pc 初始化 str 這個例子很好地說明了顯式強制轉換是多麼的危險。問題源於類型已經改變時編譯器沒有提供任何警告或錯誤提示。當咱們用 int 型地址初始化 pc 時,因爲顯式地聲明瞭這樣的轉換是正確的,所以編譯器不提供任何錯誤或警告信息。後面對 pc 的使用都假設它存放的是 char* 型對象的地址,編譯器確實沒法知道 pc 其實是指向 int 型對象的指針。所以用 pc 初始化 str是徹底正確的——雖然其實是無心義的或是錯誤的。查找這類問題的緣由至關困難,特別是若是 ip 到 pc 的強制轉換和使用 pc 初始化 string對象這兩個應用發生在不一樣文件中的時候。
4. 避免使用強制類型轉換
強制類型轉換關閉或掛起了正常的類型檢查。強烈建議程序員避免使用強制類型轉換,不依賴強制類型轉換也能寫出很好的 C++程序。
這個建議在如何看待 reinterpret_cast 的使用時很是重要。此類強制轉換老是很是危險的。類似地,使用 const_cast 也老是預示着設計缺陷。設計合理的系統應不須要使用強制轉換拋棄 const 特性。其餘的強制轉換,如 static_cast 和 dynamic_cast,各有各的用途,但都不該頻繁使用。每次使用強制轉換前,程序員應該仔細考慮是否還有其餘不一樣的方法能夠達到同一目的。若是非強制轉換不可,則應限制強制轉換值的做用域,而且記錄全部假定涉及的類型,這樣能減小錯誤發生的機會。
數組