關(guān)于C++中的類型轉(zhuǎn)換操作符

內(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)換,是把 constvolatile 屬性去掉。

下面將依次對它們進(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)換掉 expressionconst, 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_caststatic_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 類型的對象, pd1pd2 是一樣的,并且對這兩個指針執(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_castreinterpret_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_castreinterpret_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)算符用來修改類型的 constvolatile 屬性。除了 constvolatile 修飾之外, type_idexpression 的類型是一樣的。

描述

const_cast 剝離一個對象的 const 屬性,允許對常量進(jìn)行修改。

  • 常量指針被轉(zhuǎn)化成非常量指針,并且仍然指向原來的對象;
  • 常量引用被轉(zhuǎn)換成非常量引用,并且仍然指向原來的對象;
  • 常量對象被轉(zhuǎn)換成非常量對象。

Voiatileconst 類似。參見后面的例子可以了解更多信息。

舉例

給出的源代碼如下:

 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 = &ic;//編譯錯誤,從類型 ‘const int*’ 到類型 ‘int*’ 的轉(zhuǎn)換無效
25     const int *pc=&ic;
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_castdynamic_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_castdynamic_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 , ca , 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)知道 ca 的類型不符,因此 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

http://zhidao.baidu.com/question/212970514.html

http://blog.csdn.net/deyili/article/details/5354242

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容