C++強制類型轉換


C++強制類型轉換:static_cast、dynamic_cast、const_cast、reinterpret_cast

C強制轉換

  C語言中的強制轉換主要用於普通數據類型、指針的強制轉換,沒有類型檢查,轉換不安全,語法為:

(type-id)expression//轉換格式1
type-id(expression)//轉換格式2

  C++除了能使用c語言的強制類型轉換外,還新增了四種強制類型轉換:static_cast、dynamic_cast、const_cast、reinterpret_cast,主要運用於繼承關系類間的強制轉化,語法為:

//靜態轉換
static_cast<new_type>      (expression)
//動態轉換
dynamic_cast<new_type>     (expression) 
//常量轉換
const_cast<new_type>       (expression) 
//重新解釋轉換
reinterpret_cast<new_type> (expression)

  其中new type為轉換后的新類型,expression為舊類型

C++強制類型轉換

1. static_cast 靜態轉換(編譯時檢查)

  static_cast靜態轉換相當於C語言中的強制轉換,但不能實現普通指針數據(空指針除外)的強制轉換,一般用於父類和子類指針、引用間的相互轉換。

  ①用於類層次結構中基類(父類)和派生類(子類)之間指針或引用的轉換。不管是否發生多態,父子之間互轉時,編譯器都不會報錯。

    進行上行轉換(把派生類的指針或引用轉換成基類表示)是安全的;

    進行下行轉換(把基類指針或引用轉換成派生類表示)時,由於沒有動態類型檢查,所以是不安全的,但是編譯器不會報錯。

  ②用於基本數據類型之間的轉換,如把int轉換成char,把int轉換成enum。這種轉換的安全性也要開發人員來保證。

  ③把空指針轉換成目標類型的空指針。

  ④把任何指針類型轉換成空指針類型。

  ⑤可以對普通數據的const和non_const進行轉換,但不能對普通數據取地址后的指針進行const添加和消去。

  ⑥無繼承關系的自定義類型,不可轉換,不支持類間交叉轉換。

  注意:static_cast不能轉換掉expression的const、volatile、或者__unaligned屬性
 1 class Person{
 2 
 3 };
 4 
 5 class Son :public Person{
 6 
 7 };
 8 
 9 class My{};
10 
11 void test02(){
12     char a = 'c';
13     int b = static_cast<int> (a);
14     cout << b << endl;
15 
16     const char a0 = 'c';
17     char b0 = static_cast<char> (a0);
18     cout << b0 << endl;
19 
20     char a1 = 'c';
21     const char b1 = static_cast<const char> (a1);
22     cout << b1 << endl;
23 
24     //static無法丟掉常量或其他類型限定符,只限於對常量地址的指針去const
25     //const char a2 = 'c';
26     //char *b2 = static_cast<char*> (&a2);
27     //cout << b2 << endl;
28 
29     
30     //父類指針轉為子類
31     Person *p = NULL;
32     Son *s = static_cast<Son*>(p);
33 
34     //子類指針轉為父類
35     Son *s0 = NULL;
36     Person *p0 = static_cast<Person*>(s0);
37 
38     //My* my= static_cast<My*>(p); 無繼承關系的自定義數據類型不能相互轉換
39 
40     //父類對象無法轉為子類對象
41     //Person p1;
42     //Son s1 = static_cast<Son>(p1);
43     
44     //子類對象可以賦值,初始化父類對象
45     Son s2;
46     Person p2 = static_cast<Person>(s2);
47 
48     //父類引用轉為子類
49     Person p_ ;
50     Person &p3 = p_;
51     Son &s3 = static_cast<Son&>(p3);
52 
53     //子類引用轉為父類
54     Son s_;
55     Son &s4 = s_;
56     Person &p4 = static_cast<Person&>(s4);
57 
58     //空指針轉化為目標類型的指針
59     void *pPtr = NULL;
60     int *iPtr = static_cast<int*>(pPtr);
61 
62     //任何指針轉化為空指針類型
63     int *aInt = NULL;
64     void *aVoid = static_cast<void*>(aInt);
65 
66     //static_cast不能進行出void外的指針強制互轉
67     char *tmp = "abc";
68     cout << tmp << endl;
69 
70     //cout << static_cast<int*>(tmp) << endl;不能將char*型的數據轉換為int*,但C語言強轉可以
71     cout << static_cast<void*>(tmp) << endl;
72 
73     int *tmp_ = (int*)(tmp); 
74     cout << static_cast<int*>(tmp_) << endl;
75 
76     int *tmpInt = 0;
77     cout << tmpInt << endl;
78     cout << static_cast<void*>(tmpInt) << endl;
79     cout << static_cast<int*>(tmpInt) << endl;//轉為自身可以
80 }

2.dynamic_cast 動態轉換(運行時檢查)

  動態轉換的類型和操作數必須是完整類類型或空指針、空引用,說人話就是說,只能用於類間轉換,支持類間交叉轉換,不能操作普通數據

  主要用於類層次結構中基類(父類)和派生類(子類)之間指針或引用的轉換,

    ①進行上行轉換(把派生類的指針或引用轉換成基類表示)是安全的,允許轉換;

    ②進行下行轉換(把基類指針或引用轉換成派生類表示)時,由於沒有動態類型檢查,所以是不安全的,不允許轉化,編譯器會報錯;

    ③發生多態時,允許互相轉換。

    ④無繼承關系的類之間也可以相互轉換,類之間的交叉轉換。

    ⑤如果dynamic_cast語句的轉換目標是指針類型並且失敗了,則結果為0。如果轉換目標是引用類型並且失敗了,則dynamic_cast運算符將拋出一個std::bad_cast異常

3. const_cast 常量轉換

  const_cast,用於修改類型的const或volatile屬性,不能對非指針或非引用的變量添加或移除const。

 1 const int g = 20;
 2 //int h = const_cast<int>(g); //不允許對普通數據進行操作
 3 int *h = const_cast<int*>(&g);//去掉const常量const屬性
 4 
 5 const int g0 = 20;
 6 const int &g2 = g0;
 7 int &h = const_cast<int &>(g0);//去掉const引用const屬性
 8 int &h2 = const_cast<int &>(g2);//去掉const引用const屬性
 9 
10 const char *g1 = "hello";
11 char *h = const_cast<char *>(g1);//去掉const指針const屬性

4.reinterpret_cast 重新解釋轉換

  最雞肋的轉換函數,可以將任意類型轉換為任意類型,因此非常不安全。只有將轉換后的類型值轉換回到其原始類型,這樣才是正確使用reinterpret_cast方式。

  另外,static_cast和reinterpret_cast的區別主要在於多重繼承,比如

 1 class A {
 2     public:
 3     int m_a;
 4 };
 5  
 6 class B {
 7     public:
 8     int m_b;
 9 };
10  
11 class C : public A, public B {};
12 
13 void test(){
14     C c;
15     printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));
16 }

  前兩個的輸出值是相同的,最后一個則會在原基礎上偏移4個字節,這是因為static_cast計算了父子類指針轉換的偏移量,並將之轉換到正確的地址(c里面有m_a,m_b,轉換為B*指針后指到m_b處),而reinterpret_cast卻不會做這一層轉換

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM