一般來說,我們需要型別轉換的場景可以分為如下幾種:
1. c風格的強制轉換
c風格的強制轉換很簡單,有顯示轉換和隱式轉換,顯示轉換不管什麼型別之間都是用以下方式:
type a = (type) b; //將b的型別強制轉換為a的型別但是c風格的強制轉換可能帶來一些隱患,讓一些問題難以察覺.所以c++提供了一組可以用在不同場合的強制轉換的函式。
2. c++ 四種強制轉換型別函式
static_cast用法為static_cast < type > (expression),該運算子把 expression 轉換為 type 型別,但沒有執行時型別檢查來保證轉換的安全性。
應用的場合和要注意的問題:
static_cast 作用和c語言風格強制轉換的效果基本一樣,由於沒有執行時型別檢查來保證轉換的安全性,所以這型別的強制轉換和c語言風格的強制轉換都有安全隱患。
用於類層次結構中基類(父類)和派生類(子類)之間指標或引用的轉換。注意:進行上行轉換(把派生類的指標或引用轉換成基類表示)是安全的;進行下行轉換(把基類指標或引用轉換成派生類表示)時,由於沒有動態型別檢查,所以是不安全的。
用於基本資料型別之間的轉換,如把int轉換成char,把int轉換成enum。這種轉換的安全性需要開發者來維護。
把空指標轉換成目標型別的空指標。
把任何型別的表示式轉換成void型別。
static_cast不能轉換掉原有型別的const、volatile屬性。
在c++ primer 中說道:c++ 的任何的隱式轉換都是使用 static_cast 來實現。
/* 常規的使用方法 */
float a =
3.14f
int b =
static_cast
<
int>
(a);
// b 的值為 3
/* 類中的上下行轉換 */
class
base
;class
drived
:public base
;// 上行 drived -> base
//編譯通過,安全
drived d;
base *base_ptr =
static_cast
>
(&d)
;// 下行 base -> drived
//編譯通過,不安全
base base;
sub *sub_ptr =
static_cast
>
(&base)
;
const_caststatic_cast 不能將 const int* 轉成 int*,const_cast 就可以。
用法為const_cast< type >(expression)
應用的場合和要注意的問題:
1、常量指標被轉化成非常量的指標,並且仍然指向原來的物件;
2、常量引用被轉換成非常量的引用,並且仍然指向原來的物件;
3、const_cast一般用於修改指標。如const char *p形式。
const
int a =11;
const
int*p =
&a;//*p = 22; //error
//int &b = static_cast(a); //error
//int *q = static_cast(a) //error
int&b =
const_cast
<
int&
>
(a);
//ok
b =33
;//未定義行為
int*q =
const_cast
<
int*
>
(p);
//ok
*q =22;
//未定義行為
cout << a <<
" "<<
&a << endl;
cout << b <<
" "<<
&b << endl;
cout <<
*p <<
" "<< p << endl;
return0;
output:
a =110x6efe94
b =220x6efe94
*p =
220x6efe94
未定義行為:c++標準對此類行為沒有做出明確規定。同乙份**在使用不同的編譯器會有不同的效果。在 vs2017 下, 雖然**中 a, b, p 看到的位址是一樣的,但是 a 的值並沒有改變,有可能在某種編譯器實現後,這乙份**的 a 會被改變,也有可能編譯器對這類行為直接 error 或 warning。
dynamic_cast用法為dynamic_cast< type > (expression)。
應用的場合和要注意的問題:
其他三種都是編譯時完成的,dynamic_cast 是執行時處理的,執行時要進行型別檢查。
不能用於內建的基本資料型別的強制轉換
dynamic_cast 要求 <> 內所描述的目標型別必須為指標或引用。dynamic_cast 轉換如果成功的話返回的是指向類的指標或引用,轉換失敗的話則會返回 nullptr
在類的轉換時,在類層次間進行上行轉換(子類指標指向父類指標)時,dynamic_cast 和 static_cast 的效果是一樣的。在進行下行轉換(父類指標轉化為子類指標)時,dynamic_cast 具有型別檢查的功能,比 static_cast 更安全。向下轉換的成功與否還與將要轉換的型別有關,即要轉換的指標指向的物件的實際型別與轉換以後的物件型別一定要相同,否則轉換失敗。在c++中,編譯期的型別轉換有可能會在執行時出現錯誤,特別是涉及到類物件的指標或引用操作時,更容易產生錯誤。dynamic_cast操作符則可以在執行期對可能產生問題的型別轉換進行測試。
使用 dynamic_cast 進行轉換的,基類中一定要有虛函式,否則編譯不通過(類中存在虛函式,就說明它有想要讓基類指標或引用指向派生類物件的情況,此時轉換才有意義)。這是由於執行時型別檢查需要執行時型別資訊,而這個資訊儲存在類的虛函式表中,只有定義了虛函式的類才有虛函式表。
classa;
};classb:
public a ;}
;classc}
;int
main()
reinterpret_cast用法為reinterpret_cast < type > (expression)reinterpret_cast是強制型別轉換符用來處理無關型別轉換的,主要用在:
任意的指標之間的轉換
任意引用之間的轉換
指標和足夠大的整型之間的轉換
int
*ptr =
newint
(233);
uint32_t ptr_addr =
reinterpret_cast
<
uint32_t
>
(ptr)
;// 將指標 ptr 的位址的值轉換成了 unsigned int 型別的 ptr_addr 的整數值.
cout <<
<< hex << ptr << endl
cout <<
"ptr_addr 的值(hex): "
<< hex << ptr_addr << endl;
/*ptr_addr 的值(hex): 0061e6d8
*/
總結一下:
附型別轉換規則表:
C 強制型別轉換
四種型別可能很多人都常常忽略就象我一樣,但是有時還是比較有用的。不了解的建議看看,一些機制我也不是十分了解,只是將一些用法寫出來讓大家看看。強制轉化無論從語法還是語意上看,都是c 中最難看的特徵之一。但是基於c風格的轉化的語義的不明確性及其一些潛在問題。強制型別轉化最終還是被c 接受了。1.stat...
C 強制型別轉換
標準c 中主要有四種強制轉換型別運算子 const cast,reinterpret cast,static cast,dynamic cast等等。1 static cast a 將位址a轉換成型別t,t和a必須是指標 引用 算術型別或列舉型別。表示式static cast a a的值轉換為模板中...
C 強制型別轉換
關於強制型別轉換的問題,很多書都討論過,寫的最詳細的是c 之父的 c 的設計和演化 最好的解決方法就是不要使用c風格的強制型別轉換,而是使用標準c 的型別轉換符 static cast,dynamic cast。標準c 中有四個型別轉換符 static cast,dynamic cast,reint...