1 起因
之前使用類型轉換,一般都會使用
short a = 10;
int b = (int) a;
然後Qt creator就會爆出:
原因就是使用了舊時的風格,也就是C語言的風格,存在安全隱患。
因此我查詢了C++如何進行強制類型轉換。
2 C++強制類型轉換
靜態static_cast<要轉換的類型>被轉換的變量
,動態dynamic_cast<要轉換的類型>被轉換的變量
。
區別:
static_cast<>是在編譯時檢測類型,dynamic_cast<>是在運行時檢測類型。
當存在要轉換的類型爲:從基類指向派生類時,由於派生類中可能存在基類沒有的成員函數或變量,於是雖然static_cast<>編譯時,不會報錯,但是運行時,如果訪問量了基類中沒有但派生類中有的變量或函數,就可能會出現越界錯誤(段錯誤),程序被異常終止。
測試程序:
#include<iostream>
#include <string>
using namespace std;
class A
{
public:
int a;
virtual ~A(){}
//基類中必須有虛函數是因爲:
//dynamic_cast<>要求所涉及的類至少具有1個虛擬方法,
//該方法允許編譯器(如果支持RTTI)執行此附加檢查。
};
class B : public A
{
public :
string m;
double n;
short l;
void f(){
m = "hello";
}
};
int main(){
A *Pa = new A();
B *Pb = NULL;
Pb = static_cast<B*>(Pa); //下行轉換,基類指針轉換成子類
//Pb = dynamic_cast<B*>(Pa);
// Pb->m = "hehehe";
Pb->l = 7;
Pb->f();
cout<<Pb->l<<endl;//能輸出的原因的爲:基類中剛好有int類型的變量,int和int剛好可以類型轉換(換成short或者double也可以)
cout<<Pb->m <<endl;
return 0;
}
運行結果如下:上面的爲static_cast<>,下面的爲dynamic_cast<>。
也就是雖然訪問m越界了,但是還是能輸出結果(把類A下面的內存(未初始化的)轉換爲int,這樣非常不安全,後面可能會出現莫名其妙的錯誤)。
但是dynamic_cast<>,卻輸出了段錯誤,保證了程序的安全性。
3 總結
使用dynamic_cast<>的情況:
- 類層次結構中父類和子類之間指針和引用的轉換(運行時,類型檢查,保證了程序的安全性)【可以用於基類指針指向派生類的指針】
其他情況使用static_cast<>。
使用static_cast<>的情況:
- 基本數據類型間的類型轉換
- 把空指針轉換成目標類型的空指針
- 把任何類型的表達式類型轉換成void類型
- 用於類層次結構中父類和子類之間指針和引用的轉換。(僅用於指向派生類的指針,訪問指向父類的內容)
4 衍生
const_cast<>
作用:把常量對象改爲非常量對象。
注意:
- 被轉換的變量類型必須爲引用或指針。
- 在指針或引用更改值後,原始常量中值依然不變,只有變量或者指針的值改變。
使用場景:
當函數爲常量函數時,想要改變常量函數的中的參數,可以使用。
reinterpret_cast<>
作用:
- 改變指針或引用的類型(地址)
- 將指針或引用轉換爲一個足夠長度的整形(取決於操作系統的參數)
- 將整型轉換爲指針或引用類型
注意: - 強制轉換過程僅僅只是比特位的拷貝
- 不能去除const修飾符
使用場景: - 主要用於將轉換後的類型值轉換回到其原始類型(做hash函數輔助)