C++中強制類型轉換


C++強制類型轉換

C++中的強制類型轉換雖然兼容C語言中的強制類型轉換。但是並不建議在C++中使用C語言風格的強制類型轉換。C++中的強制類型轉換共有4個關鍵字分別是:static_cast,const_cast,reinterpret_cast,dynamic_cast.

static_cast

用於將一種數據類型轉換成另一種數據類型,使用格式如下:
變量1 = static_cast<變量1數據類型>(另外一種數據類型變量或表達式);
例如:

int a = 1;
float b;
b = static_cast<float>(a);  //類似於C語言中的b = (float)a;

const_cast

用於去除指針和引用的常量性,不能去除變量的常量性。使用格式如下:
指針或引用1 = const_cast<指針或引用1類型>(帶常量性的指針或引用2);
例如:

#include <iostream>
using namespace std;
int main()
{
  int a = 10;
  const int *p = &a;    // 被const修飾,不能使用該指針修改其指向內容的值  
  int *q;

  q = const_cast<int *>(p);     // 去除p的常量性給q,如果不去除直接賦值會報錯  

  *q = 20;  

  cout<<"a的地址為:"<<&a<<" a的值為:"<<a<<endl;
  cout<<"*q指向的地址為:"<<q<<" *q的值為:"<<*q<<endl;
}

執行結果如下:

a的地址為:0x61ff14a a的值為:20  
*q指向的地址為:0x61ff14a *q的值為:20   

為了加深理解,我們再看如下一段代碼:

#include <iostream>
using namespace std;

const int & Add5(int &a);

int main()
{
  const int a = 10;     //a的值不允許修改
  int b = 20;

  const int *p = &a;    //被const修飾,不能使用該指針修改其指向內容的值
  int *q;

  q = const_cast<int *>(p);     //去除p的常量性給q,如果不去除直接賦值會報錯

  *q = 20;

  cout<<"a的地址為:"<<&a<<" a的值為:"<<a<<endl;
  cout<<"*q指向的地址為:"<<q<<" *q的值為:"<<*q<<endl;

  cout<<"b的地址為:"<<&b<<" b的值為:"<<b<<endl;
  int &m = const_cast<int &>(Add5(b));    //去掉函數的const屬性,不去掉就賦值給不帶const的引用會報錯
  cout<<"調用加5函數之后"<<endl;
  cout<<"引用m指向的地址為:"<<&m<<" 引用m指向的值為:"<<m<<endl;
}

//返回輸入值+5,返回的引用不可被修改
const int & Add5(int &a)
{
  a+=5;
  return a;
}

執行結果如下:

a的地址為0x61ff10 a的值為:10
*q指向的地址為:0x61ff10 *q的值為:20
b的地址為:0x61ff0c b的值為:20
調用加5函數之后
引用m指向的地址為:0x61ff0c 引用m指向的值為:25

上面這段程序有兩點說明:

  1. 對變量a加上了const屬性,因此a的值是不會被程序所改變的。即使我們將指向a的指針的const屬性去掉重新賦值,也不會改變。但是會出現變量a和指針q指向地址相同,但值不同的現象。
  2. 對變量b的操作我們可以看出,const_cast不僅僅能去掉指針的const,也能去掉引用的const。不僅僅能去掉變量表達式的const也能去掉函數的const。
    最后,在強調一遍。const_cast不能去掉變量的const.這是編程安全的基礎。像下面這種操作是錯誤的。除了const之外,const_cast也能去掉volatile屬性,和去掉const一樣。
const int a = 10;
int b = const_cast<int>(a);     //變量的const屬性去不掉,錯誤

reinterpret_cast

reinterpret_cast這種強制類型轉換是一種非常強的強制類型轉換,它可以將任意兩個無關的指針或引用進行轉換。上面的static_cast進行強制類型轉換時,會進行編譯時的類型安全檢查,即你可以將int轉成float,將子類引用(指針)轉成父類引用(指針),子轉父和父轉子都可以,但父轉子不安全。但是你不能使用static_cast將兩個無關的東西進行轉換,比如兩個無關的類,因為編譯器在編譯的時候會檢查這個轉換是否可行,很明顯不可行。

ClassB *p = &b;
ClassA *q = static_cast<ClassA &>(p);    //如果ClassA和ClassB有關系,編譯能通過,否則不通過

但是如果使用的reinterpret_cast強制類型轉換,就不會進行靜態類型檢查直接放行通過。當然如果這兩個類如果沒有關系,那么在運行的過程就會“跑偏出錯”。為了防止在運行的過程中“跑偏”,我們除靜態類型轉換(static_cast)之外還需要一個動態的類型轉換(dynamic_cast).

dynamic_cast

前面我們介紹過了static_cast,從名稱上來看,兩個一動(dynamic)一靜(static)肯定有關系。我們知道static_cast會在編譯的過程中進行安全性檢查,而dynamic_cast會在運行的過程中進行安全性檢查。這兩個都帶安全性檢查可以防止錯誤的類型轉換導致程序跑偏。
dynamic_cast既然是動態安全性檢查,那么它肯定只能應用於指針或引用,不能用於內置的數據類型轉換(內置的數據類型轉換,在編譯階段由static_cast檢查即可)。dynamic_cast不但檢查兩個指針是否屬於同一個繼承樹(static_cast也檢查這個),還會檢測這種轉換是否可行。如果可行就會返回一個新指針,並計算出為處理多繼承的需要的必要的偏移量。如果不可行會返回NULL。因此即使我們使用reinterpret_cast強制類型轉換騙過編譯器編譯成功,如果我們在使用前再使用dynamic_cast轉換檢測一下的話,還是能發現這個錯誤的轉換的。

總結

  1. static_cast會進行靜態的安全性檢查,一般用於內置數據類型的轉換和通常的類之間的轉換。
  2. const_cast主要是用來去掉指針和引用的const和volatile類型。
  3. reinterpret_cast用於完全沒有關系指針或引用之間的轉換,比如字符指針轉整形指針。
  4. dynamic_cast通常用於基類和派生類之間的相互轉換。


免責聲明!

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



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