內(nèi)容簡介
本文對四種標(biāo)準(zhǔn)C++類型轉(zhuǎn)換符: static_cast, dynamic_cast, reinterpret_cast, const_cast 進(jìn)行介紹,通過本文應(yīng)當(dāng)能夠理解這四個類型轉(zhuǎn)換操作符的含義。
四種標(biāo)準(zhǔn)C++的類型轉(zhuǎn)換符:
-
dynamic_cast: 動態(tài)類型轉(zhuǎn)換,一般用在父類和子類指針或應(yīng)用的互相轉(zhuǎn)化; -
static_cast: 靜態(tài)類型轉(zhuǎn)換,一般是普通數(shù)據(jù)類型轉(zhuǎn)換(如int m=static_cast(3.14));) -
reinterpret_cast: 重新解釋類型轉(zhuǎn)換,很像C的一般類型轉(zhuǎn)換操作; -
const_cast: 常量類型轉(zhuǎn)換,是把const或volatile屬性去掉。
下面將依次對它們進(jìn)行相對詳細(xì)地介紹。
static_cast
支持子類指針到父類指針的轉(zhuǎn)換,并根據(jù)實際情況調(diào)整指針的值,反過來也支持,但會給出編譯警告,它作用最類似C風(fēng)格的“強(qiáng)制轉(zhuǎn)換”,一般來說可認(rèn)為它是安全的。
用法: static_cast < type-id > ( expression )
功能
該運(yùn)算符把 expression 轉(zhuǎn)換為 type-id 類型,但沒有運(yùn)行時類型檢查來保證轉(zhuǎn)換的安全性。
描述
主要如下幾種用法:
-
用于類層次結(jié)構(gòu)中基類(父類)和派生類(子類)之間指針或引用的轉(zhuǎn)換
- 進(jìn)行上行轉(zhuǎn)換(把派生類的指針或引用轉(zhuǎn)換成基類表示是安全的);
- 進(jìn)行下行轉(zhuǎn)換(把基類指針或引用轉(zhuǎn)換成派生類表示時,由于沒動態(tài)類型檢查,所以是不安全的)。
-
用于基本數(shù)據(jù)類型之間的轉(zhuǎn)換,如把
int轉(zhuǎn)換成char,把int轉(zhuǎn)換成enum這種轉(zhuǎn)換的安全性也要開發(fā)人員來保證。
把空指針轉(zhuǎn)換成目標(biāo)類型的空指針
把任何類型的表達(dá)式轉(zhuǎn)換成
void類型
注意: static_cast 不能轉(zhuǎn)換掉 expression 的 const, volitale, 或者 __unaligned 屬性。
舉例
這里,關(guān)于 static_cast 的使用舉例,通過與 reinterpret_cast 的例子進(jìn)行對比,容易理解,所以參見后面 reinterpret_cast 的使用舉例部分中對 static_cast 的使用方法。
dynamic_cast
用法: dynamic_cast < type-id > ( expression )
功能
該運(yùn)算符把 expression 轉(zhuǎn)換成 type-id 類型的對象, Type-id 必須是類的指針、類的引用或者 void * 。
描述
-
支持子類指針到父類指針的轉(zhuǎn)換,并根據(jù)實際情況調(diào)整指針的值。
這個和
static_cast不同,反過來它就不支持了(即不允許使用這個操作符號將父類強(qiáng)制轉(zhuǎn)換到子類),會導(dǎo)致編譯錯誤,所以這種轉(zhuǎn)換是最安全的轉(zhuǎn)換。如果
type-id是類指針類型,那么expression也必須是一個指針,如果type-id是一個引用,那么expression也必須是一個引用。
注: dynamic_cast 主要用于類層次間的上行轉(zhuǎn)換和下行轉(zhuǎn)換,還可以用于類之間的交叉轉(zhuǎn)換。在類層次間進(jìn)行上行轉(zhuǎn)換時, dynamic_cast 和 static_cast 的效果是一樣的;在進(jìn)行下行轉(zhuǎn)換時, dynamic_cast 具有類型檢查的功能,比 static_cast 更安全。
舉例
在類層次間進(jìn)行轉(zhuǎn)換
代碼如下:
class B{
public:
int m_iNum;
virtual void foo();
};
class D:public B{
public:
char *m_szName[100];
};
void func(B *pb){
D *pd1 = static_cast<D *>(pb);
D *pd2 = dynamic_cast<D *>(pb);
}
這里,使用 dynamic_cast 進(jìn)行轉(zhuǎn)換,如果出現(xiàn)了把指向父類對象的指針轉(zhuǎn)換成了子類的指針的時候,就會返回空值。
在上面的代碼段中,如果 pb 指向一個 D 類型的對象, pd1 和 pd2 是一樣的,并且對這兩個指針執(zhí)行 D 類型的任何操作都是安全的;但是,如果 pb 指向的是一個 B 類型的對象,那么 pd1 將是一個指向該對象的指針,對它進(jìn)行 D 類型的操作將是不安全的(如訪問 m_szName ),而 pd2 將是一個空指針。(大多數(shù)面向?qū)ο缶幊讨?,?jīng)常會在代碼中出現(xiàn)父類型的指針指向子類對象,然后在合適的時候轉(zhuǎn)換為子類對象類型,直接代碼中看不出指針?biāo)獙ο缶烤故歉割愡€是子類,通過這個 dynamic_cast 可以檢查類型,達(dá)到安全性)。
另外要注意:如果使用 dynamic_cast, B (父類)要有虛函數(shù),否則會編譯出錯; static_cast 則沒有這個限制。這是由于運(yùn)行時類型檢查需要運(yùn)行時類型信息,而這個信息存儲在類的虛函數(shù)表(關(guān)于虛函數(shù)表的概念,詳細(xì)可見 <Inside c++ object model> )中,只有定義了虛函數(shù)的類才有虛函數(shù)表,沒有定義虛函數(shù)的類是沒有虛函數(shù)表的。
類之間的交叉轉(zhuǎn)換
代碼如下:
class A{
public:
int m_iNum;
virtual void f(){}
};
class B:public A{
};
class D:public A{
};
void foo(){
B *pb = new B;
pb->m_iNum = 100;
D *pd1 = static_cast<D *>(pb); //compile error???實踐好象沒有編譯錯誤
D *pd2 = dynamic_cast<D *>(pb); //pd2 is NULL
delete pb;
}
這里,可見,如果出現(xiàn)了交叉轉(zhuǎn)換的情況那么 dynamic_cast 將會返回空值。
在函數(shù) foo 中,使用 static_cast 進(jìn)行轉(zhuǎn)換是不被允許的,將在編譯時出錯(實踐中并沒有報錯);而使用 dynamic_cast 的轉(zhuǎn)換則是允許的,結(jié)果是空指針。 保險應(yīng)當(dāng)使用 dynamic_cast 。
reinterpret_cast
用法: reinterpret_cast<type-id> (expression)
功能
它可以把一個指針轉(zhuǎn)換成一個整數(shù),也可以把一個整數(shù)轉(zhuǎn)換成一個指針(先把一個指針轉(zhuǎn)換成一個整數(shù),再把該整數(shù)轉(zhuǎn)換成原類型的指針,還可以得到原先的指針值)。 type-id 必須是一個指針、引用、算術(shù)類型、函數(shù)指針或者成員指針。
描述
reinterpret_cast 是C++里的強(qiáng)制類型轉(zhuǎn)換符,支持任何轉(zhuǎn)換,但僅僅是如它的名字所描述的“重解釋”而已。也就是說:操作符修改了操作數(shù)類型,但僅僅是重新解釋了給出的對象的比特模型而沒有進(jìn)行二進(jìn)制轉(zhuǎn)換。
例如:
int *n= new int;
double *d=reinterpret_cast<double*> (n);
在進(jìn)行計算以后, d 包含無用值.這是因為 reinterpret_cast 僅僅是復(fù)制 n 的比特位到 d, 沒有進(jìn)行必要的分析。
reinterpret_cast 是為了映射到一個完全不同類型的意思,這個關(guān)鍵詞在我們需要把類型映射回原有類型時用到它。我們映射到的類型僅僅是為了故弄玄虛和其他目的,這是所有映射中最危險的(C++編程思想中的原話)。將 static_cast 和 reinterpret_cast 對比一下進(jìn)行解釋,比較容易理解: static_cast 操作符修改了操作數(shù)類型,但是 reinterpret_cast 僅僅是重新解釋了給出的對象的比特模型而沒有進(jìn)行二進(jìn)制轉(zhuǎn)換。
例如:
int n=9;
double d=static_cast<double>(n);
上面的例子中, 我們將一個變量從 int 轉(zhuǎn)換到 double 。這些類型的二進(jìn)制表達(dá)式是不同的,所以將整數(shù)9轉(zhuǎn)換到雙精度整數(shù)9, static_cast 需要正確地為雙精度整數(shù) d 補(bǔ)足比特位。其結(jié)果為 9.0 。
而 reinterpret_cast 的行為卻不同:
int n=9;
double d=reinterpret_cast<double & >(n);
這里, 和 static_cast 不同,在進(jìn)行計算以后, d 包含無用值。這是因為 reinterpret_cast 僅僅是復(fù)制 n 的比特位到 d, 沒有進(jìn)行必要的分析。
因此, 需要謹(jǐn)慎使用 reinterpret_cast 。
舉例
這個例子,將 static_cast 和 reinterpret_cast 對比進(jìn)行測試,具體的輸出參見其中的注釋。
1 #include <iostream>
2 using std::cout;
3 using std::endl;
4 class CBaseX
5 {
6 public:
7 int x;
8 CBaseX() { x = 10; }
9 void foo() { printf("CBaseX::foo() x=%d/n", x); }
10 };
11 class CBaseY
12 {
13 public:
14 int y;
15 int* py;
16 CBaseY() { y = 20; py = &y; }
17 void bar() { printf("CBaseY::bar() y=%d, *py=%d/n", y, *py);}
18 };
19 class CDerived : public CBaseX, public CBaseY
20 {
21 public:
22 int z;
23 };
24
25 int main(int argc, char *argv[])
26 {
27 float f = 12.3;
28 float* pf = &f;
29
30 //基本類型的轉(zhuǎn)換
31 cout<<"=================Basic Cast================="<<endl;
32 //======static cast<>的使用:
33 int n = static_cast<int>(f); //成功編譯
34 cout<<"n is :"<<n<<endl;//n = 12
35 //int* pn = static_cast<int*>(pf);//編譯錯誤,指向的類型是無關(guān)的,不能將指針指向無關(guān)的類型
36 void* pv = static_cast<void*>(pf);//編譯成功
37 int* pn2 = static_cast<int*>(pv);//成功編譯, 但是 *pn2是無意義的內(nèi)存(rubbish)
38 cout<<"pf is:"<<pf<<",pv is:"<<pv<<",pn2 is:"<<pn2<<endl;//三者值一樣
39 cout<<"*pf is:"<<*pf<<",*pn2 is:"<<*pn2<<endl;//pf=12.3,pn2是無用值,注意無法使用"*pv"因為編譯錯。
40
41 //======reinterpret_cast<>的使用:
42 //int i = reinterpret_cast<int>(f);//編譯錯誤,類型‘float’到類型‘int’的轉(zhuǎn)換無效.
43 //成功編譯, 但是 *pn 實際上是無意義的內(nèi)存,和 *pn2一樣
44 int* pi = reinterpret_cast<int*>(pf);
45 cout<<"pf is:"<<pf<<",pi is:"<<pi<<endl;//值一樣
46 cout<<"*pf is:"<<*pf<<",*pi is:"<<*pi<<endl;//pi是無用值,和pn2一樣。
47
48
49 //對象類型的轉(zhuǎn)換
50 cout<<"=================Class Cast================="<<endl;
51 CBaseX cx;
52 CBaseY cy;
53 CDerived cd;
54
55 CDerived* pD = &cd;
56 CBaseX *pX = &cx;
57 CBaseY *pY = &cy;
58 cout<<"CDerived* pD = "<<pD<<endl;
59
60 //======static_cast<>的使用:
61 CBaseY* pY1 = pD; //隱式static_cast轉(zhuǎn)換
62 //不一樣是因為多繼承,pD還要前移動以便也指向CBaseX.
63 cout<<"CDerived* pD = "<<pD<<",CBaseY* pY1 = "<<pY1<<endl;//pY1=pD+4!!!!!!
64
65 //CDerived* pD1 = pY1;//編譯錯誤,類型 ‘CBaseY*’ 到類型 ‘CDerived*’ 的轉(zhuǎn)換無效
66 CDerived* pD1 = static_cast<CDerived*>(pY1);//成功編譯
67 cout<<"CDerived* pD1 = "<<pD1<<endl;//現(xiàn)在 pD1 = pD
68
69 //pX = static_cast<CBaseX*>(pY);//編譯錯誤,從類型 ‘CBaseY*’ 到類型 ‘CBaseX*’ 中的 static_cast 無效。
70 pD1 = static_cast<CDerived*>(pY);//竟然可以編譯通過!!!!!!
71 cout<<"CDerived* pD1 = "<<pD1<<",CBaseY *pY = "<<pY<<endl;//現(xiàn)在 pD1 = pY-4
72 //======reinterpret_cast<>的使用:
73 CBaseY* pY2 = reinterpret_cast<CBaseY*>(pD);// 成功編譯, 但是 pY2 不是 CBaseY*
74 cout<<"CDerived* pD = "<<pD<<",CBaseY* pY2 = "<<pY2<<endl;//pY2=pD!!!!!!
75
76 //======通過void的轉(zhuǎn)換注意:
77 CBaseY* ppY = pD;
78 cout<<"CDerived* pD = "<<pD<<",CBaseY* ppY = "<<ppY<<endl;//ppY = pD + 4
79
80 void* ppV1 = ppY; //成功編譯
81 cout<<"CBaseY* ppY = "<<ppY<<",void* ppV1 = "<<ppV1<<endl;//ppV1 = ppY
82
83 //CDerived* ppD2 = ppV1;//編譯錯誤,類型‘void*’ 到類型 ‘CDerived*’的轉(zhuǎn)換無效
84 CDerived* ppD2 = static_cast<CDerived*>(ppV1);
85 cout<<"CDerived* ppD2 = "<<ppD2<<endl;//ppD2 = ppY, 但是我們預(yù)期 ppD2 = ppY - 4 = pD
86 //ppD2->bar();//系統(tǒng)崩潰,段錯誤
87 return 0;
88 }
這里,需要注意的地方是:
-
第63行中基類指針
pY1被賦予子類指針pD后,pY1=pD+4而不是pD,因為pD是多繼承,pD還要前移動以便也指向CBaseX.內(nèi)存布局大致如下:
+CDerived------------------+ | +CBase X--------+ |\ | | int x | | 4 bytes | +---------------+ |/ | | | +CBase Y--------+ | | | int y,*py | | | +---------------+ | +--------------------------+ 第69行和70行的可以將父類指針用
static_cast強(qiáng)制轉(zhuǎn)換成子類指針,但是兩個無關(guān)的類的指針之間卻不能轉(zhuǎn)換。第74行中使用
reinterpret_cast將子類指針強(qiáng)制轉(zhuǎn)換賦給父類指針后,卻沒有像static_cast那樣將父類指針位置調(diào)整以指向正確的對象位置,這樣導(dǎo)致雖然兩者值是一樣的,但是父指針?biāo)赶虻膬?nèi)容卻不是父對象了。-
第76行之后使用
void將子類轉(zhuǎn)換成父類再轉(zhuǎn)回子類,卻無法使用了。因為任何指針可以被轉(zhuǎn)換到
void*,而void*可以被向后轉(zhuǎn)換到任何指針(對于static_cast<>和reinterpret_cast<>轉(zhuǎn)換都可以這樣做),如果沒有小心處理的話錯誤可能發(fā)生。一旦我們已經(jīng)轉(zhuǎn)換指針為void*,我們就不能輕易將其轉(zhuǎn)換回原類(因為原類的信息在代碼中看不到了),所以使用void轉(zhuǎn)換的時候一定要小心。在上面的例子中,從一個void*返回CDerived*的唯一方法是將其轉(zhuǎn)換為CBaseY*然后再轉(zhuǎn)換為CDerived*。但是如果我們不能確定它是CBaseY*還是CDerived*,這時我們不得不用dynamic_cast<>或typeid[2](dynamic_cast<>需要類成為多態(tài),即包括“虛”函數(shù),并因此而不能成為void*)。
[其它]
dynamic_cast<> ,從另一方面來說,可以防止一個泛型 CBaseY* 被轉(zhuǎn)換到 CDerived* 。
const_cast
用法: const_cast<type_id> (expression)
功能
該運(yùn)算符用來修改類型的 const 或 volatile 屬性。除了 const 或 volatile 修飾之外, type_id 和 expression 的類型是一樣的。
描述
const_cast 剝離一個對象的 const 屬性,允許對常量進(jìn)行修改。
- 常量指針被轉(zhuǎn)化成非常量指針,并且仍然指向原來的對象;
- 常量引用被轉(zhuǎn)換成非常量引用,并且仍然指向原來的對象;
- 常量對象被轉(zhuǎn)換成非常量對象。
Voiatile 和 const 類似。參見后面的例子可以了解更多信息。
舉例
給出的源代碼如下:
1 #include <iostream>
2 using std::cout;
3 using std::endl;
4
5 class CTest
6 {
7 public:
8 CTest(int i){m_val = i;cout<<"construction"<<m_val<<endl;}
9 ~CTest(){cout<<"destructionn"<<endl;}
10 void SelfAdd(){m_val++;};
11 int m_val;
12 };
13
14 int main(int argc, char *argv[])
15 {
16 const int ic = 100;
17 //int cc = const_cast<int>(ic);//編譯錯誤
18 int cc = const_cast<int&>(ic);
19 cout<<cc<<endl;//輸出100
20 //const_cast<int &>(&ic)=200;//編譯錯誤,從類型 ‘const int*’ 到類型 ‘int&’ 中的 const_cast 無效
21 const_cast<int &>(ic)=200;
22 cout<<ic<<endl;//輸出100
23 cout<<*(&ic)<<endl;//輸出100
24 //int *pc = ⁣//編譯錯誤,從類型 ‘const int*’ 到類型 ‘int*’ 的轉(zhuǎn)換無效
25 const int *pc=⁣
26 //const_cast<int &>(pc)=200;//編譯錯誤,從類型 ‘const int**’ 到類型 ‘int*’ 中的 const_cast 無效
27 const_cast<int &>(ic)=200;
28 //printf("%d,%d/n", ic, *pc);
29 cout<<ic<<','<<*pc<<endl;//100,200
30 //int *ppc = const_cast<int*>(ic);//編譯錯誤
31 int *ppc = const_cast<int*>(&ic);
32 *ppc = 300;
33 cout<<ic<<','<<*ppc<<endl;//100,300
34
35 const CTest test(1000);
36 CTest test2(1050);
37 //test = test2;//編譯錯誤,無法給常量賦值
38 const_cast<CTest &>(test)= test2;
39 cout<<test.m_val<<endl;//輸出1050
40 }
這里,結(jié)果輸出參見每行代碼相應(yīng)的注釋。根據(jù)結(jié)果可知:
- 凡是對結(jié)構(gòu)體或類進(jìn)行這個轉(zhuǎn)換,都是成功的。
- 對
char,short等基本類型的轉(zhuǎn)換,通過直接打印變量顯示其值都是不成功的,但是通過指針卻能顯示出修改之后的值。
通過對代碼進(jìn)行反匯編,可知,雖然本身我們沒使用優(yōu)化,但系統(tǒng)還是對 ic 這個 const 進(jìn)行了預(yù)編譯般的替換,將它替換成 64h (十六進(jìn)制的64就是十進(jìn)制的100),這肯定不是一般用戶想要的結(jié)果,如果它不是一個C++的規(guī)范,應(yīng)該算是個C++的bug吧。
其他
注意下面一些問題。
操作對象
const_cast 操作的對象必須是 pointer, reference, nor a pointer-to-data-member type,如下代碼是錯誤的:
const int a = 5;
int aa = const_cast<int>(a);
而使用引用的方式,如下卻是正確的:
const int a = 5;
int aa = const_cast<int&>(a);
(2)可能的誤解
可能上面的描述誤解的地方,根據(jù)參考資料中的一個評論,說: const_cast 只能修改變量的常引用的 const 屬性,和變量的常指針的 const 屬性,還有對象的 const 屬性。要想改變常量本身的值是不可能的,也就是說,你改變的是引用的 const 屬性,而不是常量本身的 const 屬性。估計 const int ic = 100; 定義的時候就已經(jīng)將這個基礎(chǔ)類型對象放入常量符號表里面了,永遠(yuǎn)不會改變它的值。
五、其它
做為一個對前面所說的四種類型轉(zhuǎn)換操作符的補(bǔ)充,對它們之間的區(qū)別大致進(jìn)行說明一下,如下。
static_cast 和 dynamic_cast 的對比
-
static_cast在編譯期間發(fā)現(xiàn)錯誤。對于基本類型,它不允許將一種類型的指針指向另一種類型。所以如下代碼是錯誤的:
float f = 12.3; float* pf = &f; int* pn = static_cast<int*>(pf);//編譯錯誤,指向的類型是無關(guān)的,不能將指針指向無關(guān)的類型對于復(fù)合類型(例如類、結(jié)構(gòu)、聯(lián)合)它允許轉(zhuǎn)換子對象地址賦值給父指針,也允許轉(zhuǎn)換父對象地址賦值給子指針,但是不允許兩個無關(guān)的類之間的轉(zhuǎn)換,所以如下是錯誤的:
CBaseX *pX = &cx; CBaseY *pY = &cy; pX = static_cast<CBaseX*>(pY);//編譯錯誤,從類型 ‘CBaseY*’ 到類型 ‘CBaseX*’ 中的 static_cast 無效。 -
dynamic_cast在運(yùn)行期間發(fā)生錯誤,它只允許它允許轉(zhuǎn)換子對象地址賦值給父指針,其它情況都返回空。例如:
B *pb = new B; D *pd = dynamic_cast<D *>(pb); //pd is NULL delete pb;
static_cast, dynamic_cast, 和 reinterpret_cast 之間的對比
轉(zhuǎn)換的內(nèi)容
static_cast 和 dynamic_cast 可轉(zhuǎn)換指針之間或?qū)嵗g
就是說,這兩個操作符可以執(zhí)行指針到指針的轉(zhuǎn)換,或?qū)嵗旧淼綄嵗旧淼霓D(zhuǎn)換,但不能在實例和指針之間轉(zhuǎn)換。
static_cast 只能提供編譯時的類型安全,而 dynamic_cast 可以提供運(yùn)行時類型安全。
舉個例子:
class a;class b:a;class c;
上面?zhèn)€類 a 是基類, b 繼承 a , c 和 a , b 沒有關(guān)系。假設(shè)有一個函數(shù) void function(a&a); 現(xiàn)在有一個對象是 b 的實例 b ,一個 c 的實例 c 。 function(static_cast<a&>(b) 可以通過而 function(static<a&>(c)) 不能通過編譯,因為在編譯的時候編譯器已經(jīng)知道 c 和 a 的類型不符,因此 static_cast 可以保證安全。
reinterpret_cast 可任意轉(zhuǎn)換32bit的指針、實例
就是說,它可以轉(zhuǎn)換任意一個32bit整數(shù),包括所有的指針和整數(shù)??梢园讶魏握麛?shù)轉(zhuǎn)成指針,也可以把任何指針轉(zhuǎn)成整數(shù),以及把指針轉(zhuǎn)化為任意類型的指針,威力最為強(qiáng)大!但不能將非32bit的實例轉(zhuǎn)成指針。總之,只要是32bit的東東,怎么轉(zhuǎn)都行!
對于剛剛說的例子,下面我們騙一下編譯器,先把 c 轉(zhuǎn)成類型 a 。
b& ref_b = reinterpret_cast<b&>c;
這樣,
-
function(static_cast<a&>(ref_b))就通過了!因為從編譯器的角度來看,在編譯時并不能知道ref_b實際上是c! - 而
function(dynamic_cast<a&>(ref_b))編譯時能過,在運(yùn)行時卻失敗了,因為dynamic_cast在運(yùn)行時檢查了ref_b的實際類型,這樣怎么也騙不過去了。
檢測轉(zhuǎn)換的時機(jī)
在不同時機(jī)對轉(zhuǎn)換進(jìn)行轉(zhuǎn)換,其安全性級別也不同,一般而言,這幾個運(yùn)算符,若運(yùn)行時檢測安全性最高,編譯時次之,而不檢測最危險。
- 運(yùn)行時:在應(yīng)用多態(tài)編程時,當(dāng)我們無法確定傳過來的對象的實際類型時使用
dynamic_cast, - 編譯時:如果能保證對象的實際類型,用
static_cast就可以了, - 不檢測:至于
reinterpret_cast很象c語言那樣的暴力轉(zhuǎn)換。
總之, dynamic_cast 運(yùn)行檢測, static_cast 編譯檢測, reinterpret_cast 不檢測
以上是從網(wǎng)上搜集的,以及根據(jù)自己的理解對C++中四種操作符號的總結(jié),如有不準(zhǔn)確的地方,感謝讀者的告知。另外文件的圖示內(nèi)容由于格式轉(zhuǎn)換所以不太準(zhǔn)確,可以存成文本格式的。_
參考資料
http://zhidao.baidu.com/question/81318972.html
http://blog.csdn.net/guogangj/article/details/1545119