天天看點

c++ 資料類型轉換: static_cast dynamic_cast reinterpret_cast const_cast

【目錄】

引言

static_cast 定義

dynamic_cast 定義

舉例:下行轉換(把基類的指針或引用轉換成子類表示)

舉例:上行轉換(把子類的指針或引用轉換成基類表示)

舉例: static_cast 用于基本類型之間、基本類型指針和空指針間的轉換

reinterpret_cast 定義

舉例:reinterpret_cast用法

const_cast 定義

舉例:const_cast用法

總結

c語言中我們經常使用類似于 int a =(int)3.14等這種強制類型轉換

标準c++的類型轉換符:static_cast 、dynamic_cast、 reindivter_cast、 const_cast, 以下分别介紹他們的用法以及舉例說明

以下代碼編譯運作環境:codeblock with gcc in win7(x64)

【1】static_cast 

用法:static_cast < type-id > ( exdivssion ) 

該運算符把exdivssion轉換為type-id類型,但沒有運作時類型檢查來保證轉換的安全性。它主要有如下幾種用法:

①用于類層次結構中基類和子類之間指針或引用的轉換。

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

  進行下行轉換(把基類指針或引用轉換成子類表示)時,由于沒有動态類型檢查,是以是不安全的。

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

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

④把任何類型的表達式轉換成void類型。

注意:static_cast 不能轉換掉exdivssion的const、volitale、或者__unaligned屬性。

msdn官方解釋:http://msdn.microsoft.com/en-us/library/c36yw7x9(v=vs.80).aspx

【2】dynamic_cast

用法:dynamic_cast < type-id > ( exdivssion )

該運算符把exdivssion轉換成type-id類型的對象。Type-id必須是類的指針、類的引用或者void *;

如果type-id是類指針類型,那麼exdivssion也必須是一個指針,如果type-id是一個引用,那麼exdivssion也必須是一個引用。

dynamic_cast主要用于類層次間的上行轉換和下行轉換,還可以用于類之間的交叉轉換。

在類層次間進行上行轉換時,dynamic_cast和static_cast 的效果是一樣的;

在進行下行轉換時,dynamic_cast具有類型檢查的功能,比static_cast 更安全。

msdn官方解釋:http://msdn.microsoft.com/en-us/library/cby9kycs(v=vs.80).aspx

需要注意的是如果基類中不含虛函數,dynamic_cast 下行轉換編譯會出錯

1 #include<iostream>
 2 using namespace std;
 3 
 4 class father
 5 {
 6 public:
 7     void fun1()
 8     {
 9         cout<<"this is father fun1 call\n";
10     }
11     virtual void fun()
12     {
13         cout<<"this is father fun call\n";
14     }
15 };
16 
17 class son: public father
18 {
19 public:
20     void fun2()
21     {
22         cout<<"this is son fun2 call\n";
23     }
24     void fun()
25     {
26         cout<<"this is the son fun call\n";
27     }
28     int k;
29 };
30 
31 int main()
32 {
33     father *pf, f;
34     son *ps, s;
35 
36     pf = &f;// 基類的指針指向基類對象
37     ps = static_cast<son *>(pf);//這種轉換是不安全的,行為是不确定的
38     if(ps != NULL)
39     {
40         ps->fun(); //在本文編譯環境下,執行父類的fun
41         //本文編譯環境下,一下語句可以執行
42         ps->fun2();
43         ps->k = 1;
44     }
45     ps = dynamic_cast<son *>(pf);//轉換後ps = NULL
46     if(ps == NULL)
47         cout<<"dynamic_cast: ps = NULL\n";
48     cout<<"-----------------------------------------------------------------\n";
49     pf = &s; //基類指針開始指向子類對象
50     //此時,兩種轉換都是安全的
51     ps = static_cast<son *>(pf);
52     if(ps != NULL)
53     {
54         ps->fun();
55         ps->fun2();
56         ps->k = 1;
57     }
58     ps = dynamic_cast<son *>(pf);//轉換後ps = NULL
59     if(ps != NULL)
60     {
61         ps->fun();
62         ps->fun2();
63         ps->k = 2;
64     }
65 }      

結果:

c++ 資料類型轉換: static_cast dynamic_cast reinterpret_cast const_cast
1 //類定義同上
 2 int main()
 3 {
 4     father *pf, f;
 5     son *ps, s;
 6 
 7     ps = &s;// 子類的指針指向子類對象
 8     //此時兩種轉換都是安全的
 9     pf = static_cast<father *>(ps);
10     if(pf != NULL)
11     {
12         pf->fun();
13     }
14     pf = dynamic_cast<father *>(ps);
15     if(pf != NULL)
16     {
17         pf->fun();
18     }
19 
20 }      
c++ 資料類型轉換: static_cast dynamic_cast reinterpret_cast const_cast

舉例: static_cast 用于基本類型之間、基本類型指針和空指針間的轉換(不能用于基本類型指針之間轉換)。

注意:基本類型由于表示數值範圍的不同,是以需要使用者保證轉換的安全。另外dynamic_cast不能用于此類轉換

1 int main()
 2 {
 3     //基本類型間的轉換,需要使用者保證安全
 4     int a = 1000;
 5     char c = static_cast<char>(a);//不安全,1000超過了char的表示範圍
 6     cout<<c<<endl;//輸出空
 7     a = 49;
 8     c = static_cast<char>(a);//安全,輸出字元‘1’
 9     cout<<c<<endl;
10     //c = dynamic_cast<char>(a); 錯誤
11     cout<<"-----------------------------------------------------------------\n";
12     //void *和基本類型指針的轉換,需要使用者保證轉換安全
13     a = 49;
14     void *pv;
15     pv = &a;
16     int *pi = static_cast<int *>(pv);//void * 轉換為int *
17     cout<<*pi<<endl; //輸出49
18     //pi = dynamic_cast<int *>(pv); 錯誤
19     char *pc = static_cast<char *>(pv);//void *轉char*
20     cout<<*pc<<endl;//輸出字元‘1’
21     void *pv2 = static_cast<void *>(pc);// char * 轉void *
22     cout<<*((char *)pv2)<<endl;////輸出字元‘1’
23 }      
c++ 資料類型轉換: static_cast dynamic_cast reinterpret_cast const_cast

【3】reinterpret_cast

用法:reinterpret_cast<type-id> (exdivssion)

reinterpret_cast運算符是用來處理無關類型之間的轉換;它會産生一個新的值,這個值會有與原始參數(expressoin)有完全相同的比特位。按照reinterpret的字面意思“重新解釋”,即對資料的比特位重新解釋。

IBM的C++指南 裡明确告訴了我們reinterpret_cast可以,或者說應該在什麼地方用來作為轉換運算符:

  • 從指針類型到一個足夠大的整數類型
  • 從整數類型或者枚舉類型到指針類型
  • 從一個指向函數的指針到另一個不同類型的指向函數的指針
  • 從一個指向對象的指針到另一個不同類型的指向對象的指針
  • 從一個指向類函數成員的指針到另一個指向不同類型的函數成員的指針
  • 從一個指向類資料成員的指針到另一個指向不同類型的資料成員的指針

總結來說:reinterpret_cast用在任意指針(或引用)類型之間的轉換;以及指針與足夠大的整數類型之間的轉換;從整數類型(包括枚舉類型)到指針類型,無視大小。

msdn官方解釋:http://msdn.microsoft.com/en-us/library/e0w9f63b(v=vs.80).aspx

1 int main()
 2 {
 3    int a = 49;
 4    int *pi = &a;
 5    char *pc = reinterpret_cast<char*>(pi);//int * 到char *,使用者自己安全
 6    cout<<*pc<<endl; //輸出字元"1"
 7    unsigned long b = reinterpret_cast<unsigned long>(pc);//char * 轉 unsigned long
 8    cout<<b<<endl;//輸出pc指向位址(即a的位址)對應的整數
 9    int *pi2 = reinterpret_cast<int *>(b);//unsigned long 轉 int*
10    cout<<*pi2<<endl; //輸出49
11 }      
c++ 資料類型轉換: static_cast dynamic_cast reinterpret_cast const_cast

【4】const_cast 

用法:const_cast<type-id> (exdivssion)

該運算符用來修改類型的const、volatile、__unaligned屬性。除了const 、volatile、__unaligned修飾之外, type_id和exdivssion的類型是一樣的。

常量指針被轉化成非常量指針,并且仍然指向原來的對象;

常量引用被轉換成非常量引用,并且仍然指向原來的對象;常量對象被轉換成非常量對象。

msdn官方解釋:http://msdn.microsoft.com/en-us/library/bz6at95h(v=vs.80).aspx

1 int main()
2 {
3    const int a = 100;
4    int *b = const_cast<int *>(&a);//const int * 轉int *
5    cout<<*b<<endl; //輸出100
6    cout<<&a<<" "<<b<<endl; //兩者值相同,表明b指向a的位址,隻是const屬性變了
7 }      
c++ 資料類型轉換: static_cast dynamic_cast reinterpret_cast const_cast

總結:

類指針或引用的上行轉換static_cast 和 dynamic_cast 都可以

類指針或引用的下行轉換用dynamic_cast并且判斷轉換後是否為空

基本資料類型之間的轉換用static_cast, 但是由于數值範圍的不同,需要使用者保證轉換的安全性

不同類型之間的指針或引用的轉換用reinterpret_cast,它的本質是對指向記憶體的比特位的重解釋

消除資料的const、volatile、__unaligned屬性,用const_cast

【版權聲明】轉載請注明出處 http://www.cnblogs.com/TenosDoIt/p/3175217.html

繼續閱讀