C++四種強制類型轉換


在C++語言中新增了四個關鍵字static_cast、const_cast、reinterpret_cast和dynamic_cast。新類型的強制轉換可以提供更好的控制強制轉換過程。

static_cast

static_cast用於將一種數據類型強制轉換為另一種數據類型。

int a = 7;
int b = 3;
double result = static_cast<double>(a) / static_cast<double>(b);

可以使用static_cast找回存在於void*指針中的值

double a = 7;
void* p = &a;
double* dp = static_cast<double*>(p);

 

它主要有如下幾種用法:
    (1)用於類層次結構中基類和派生類之間指針或引用的轉換
      進行上行轉換(把派生類的指針或引用轉換成基類表示)是安全的
      進行下行轉換(把基類的指針或引用轉換為派生類表示),由於沒有動態類型檢查,所以是不安全的
    (2)用於基本數據類型之間的轉換,如把int轉換成char。這種轉換的安全也要開發人員來保證
    (3)把空指針轉換成目標類型的空指針
    (4)把任何類型的表達式轉換為void類型
    注意:static_cast不能轉換掉expression的const、volitale或者__unaligned屬性。

const_cast

const_cast用於強制去掉不能被修改的常數特性,但需要特別注意的是const_cast不是用於去除變量的常量性,而是去除指向常數對象的指針或引用的常量性,其去除常量性的對象必須為指針或引用。

用法:const_cast<type_id> (expression)
    該運算符用來修改類型的const或volatile屬性。除了const 或volatile修飾之外, type_id和expression的類型是一樣的。
    常量指針被轉化成非常量指針,並且仍然指向原來的對象;
    常量引用被轉換成非常量引用,並且仍然指向原來的對象;常量對象被轉換成非常量對象。

const double a = 7;
const double* p = &a;
double* q = const_cast<double*>(p);
*q = 20; //通過q寫值是未定義的行為

reinterpret_cast

在C++語言中,reinterpret_cast主要有三種強制轉換用途:改變指針或引用的類型、將指針或引用轉換為一個足夠長度的整形、將整型轉換為指針或引用類型

用法:reinterpret_cast<type_id> (expression)
    type-id必須是一個指針、引用、算術類型、函數指針或者成員指針。
    它可以把一個指針轉換成一個整數,也可以把一個整數轉換成一個指針(先把一個指針轉換成一個整數,在把該整數轉換成原類型的指針,還可以得到原先的指針值)。
    在使用reinterpret_cast強制轉換過程僅僅只是比特位的拷貝,因此在使用過程中需要特別謹慎!

dynamic_cast

 用法:dynamic_cast<type_id> (expression)

 

(1)其他三種都是編譯時完成的,dynamic_cast是運行時處理的,運行時要進行類型檢查。

(2)不能用於內置的基本數據類型的強制轉換。

(3)dynamic_cast轉換如果成功的話返回的是指向類的指針或引用,轉換失敗的話則會返回NULL。

(4)使用dynamic_cast進行轉換的,基類中一定要有虛函數,否則編譯不通過。

        基類中需要檢測有虛函數的原因:類中存在虛函數,就說明它有想要讓基類指針或引用指向派生類對象的情況,此時轉換才有意義。

         這是由於運行時類型檢查需要運行時類型信息,而這個信息存儲在類的虛函數表(關於虛函數表的概念,詳細可見<Inside c++ object model>)中,

        只有定義了虛函數的類才有虛函數表。

 (5)在類的轉換時,在類層次間進行上行轉換時,dynamic_cast和static_cast的效果是一樣的。在進行下行轉換時,dynamic_cast具有類型檢查的功能,比static_cast更安全。

        向上轉換,即為子類指針指向父類指針(一般不會出問題);向下轉換,即將父類指針轉化子類指針。

       向下轉換的成功與否還與將要轉換的類型有關,即要轉換的指針指向的對象的實際類型與轉換以后的對象類型一定要相同,否則轉換失敗。

        在C++中,編譯期的類型轉換有可能會在運行時出現錯誤,特別是涉及到類對象的指針或引用操作時,更容易產生錯誤。Dynamic_cast操作符則可以在運行期對可能產生問題的類型轉換進行測試。

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 using namespace std;
 5 
 6 class Base{
 7 
 8 public:
 9     Base() :str(nullptr){}
10     Base(string s) :str(s){}
11     virtual void print()
12     {
13         cout << str << "  ";
14     }
15 private:
16     string str;
17 };
18 
19 class Derived:public Base
20 
21 {
22 public:
23     Derived(){}
24     Derived(string s,int i) :Base(s),ival(i){}
25     void print()
26     {
27         Base::print();
28         cout << ival << endl;
29     }
30     void print_ival()
31     {
32         cout << "僅輸出ival的值:" << ival << endl;
33     }
34 private:
35     int ival;
36 };
37 
38 
39 int main()
40 {
41     Base base("aaa");
42     Derived de("xxx", 111);
43     //指針dynamic_cast
44     Base* pb = &de;
45     if (Derived* pd = dynamic_cast<Derived*>(pb))
46     {
47         pd->print_ival();
48     }
49     else
50     {
51         //轉換失敗返回空指針
52         cout << "type error..." << endl;
53     }
54     //引用dynamic_cast
55     Base& rf = de;
56     try
57     {
58         Derived& d = dynamic_cast<Derived&>(rf);
59         d.print_ival();
60     }
61     catch (const std::bad_cast& ex)
62     {
63         //轉換失敗,拋出std::bad_cast異常
64         cout << ex.what();
65     }
66     system("pause");
67 }
View Code

 


免責聲明!

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



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