在C++語言中新增了四個關鍵字static_cast、const_cast、reinterpret_cast和dynamic_cast。這四個關鍵字都是用于強制類型轉換的。
static_cast
在C++語言中static_cast用于資料類型的強制轉換,強制将一種資料類型轉換為另一種資料類型。例如将整型資料轉換為浮點型資料。
C語言所采用的類型轉換方式:
int a = 10;
int b = 3;
double result = (double)a / (double)b;
在C++語言中,我們可以采用static_cast關鍵字來進行強制類型轉換,如下所示:
int a = 10;
int b = 3;
double result = static_cast<double>(a) / static_cast<double>(b);
格式可以概括為如下形式:
static_cast <類型說明符> (變量或表達式)
const_cast
在C語言中,const限定符通常被用來限定變量,用于表示該變量的值不能被修改。而const_cast則正是用于強制去掉這種不能被修改的常數特性,但需要特别注意的是const_cast不是用于去除變量的常量性,而是去除指向常數對象的指針或引用的常量性,其去除常量性的對象必須為指針或引用。
const int a = 10;
const int * p = &a;
*p = 20; //compile error
int b = const_cast<int>(a); //compile error
第一個編譯錯誤是*p因為具有常量性,其值是不能被修改的;另一處錯誤是const_cast強制轉換對象必須為指針或引用。
const_cast關鍵字的使用
#include<iostream>
using namespace std;
int main()
{
const int a = 10;
const int * p = &a;
int *q;
q = const_cast<int *>(p);
*q = 20; //fine
cout <<a<<" "<<*p<<" "<<*q<<endl;
cout <<&a<<" "<<p<<" "<<q<<endl;
return 0;
}
将變量a聲明為常量變量,同時聲明了一個const指針指向該變量(此時如果聲明一個普通指針指向該常量變量的話是不允許的),之後定義了一個普通的指針*q。将p指針通過const_cast去掉其常量性,并賦給q指針。之後再修改q指針所指位址的值時,這是不會有問題的。
最後将結果列印出來,運作結果如下:
10 20 20
002CFAF4 002CFAF4 002CFAF4
檢視運作結果,問題來了,指針p和指針q都是指向a變量的,指向位址相同,而且經過調試發現002CFAF4位址内的值确實由10被修改成了20,這是怎麼一回事呢?為什麼a的值列印出來還是10呢?
變量a一開始就被聲明為一個常量變量,不管後面的程式怎麼處理,它就是一個常量,就是不會變化的。試想一下如果這個變量a最終變成了20會有什麼後果呢?對于這些簡短的程式而言,如果最後a變成了20,我們會一眼看出是q指針修改了,但是一旦一個項目工程非常龐大的時候,在程式某個地方出現了一個q這樣的指針,它可以修改常量a,這是一件很可怕的事情的,可以說是一個程式的漏洞,畢竟将變量a聲明為常量就是不希望修改它,如果後面能修改,這就太恐怖了。
在上面的例子中我們稱“*q=20”語句為未定義行為語句,所謂的未定義行為是指在标準的C++規範中并沒有明确規定這種語句的具體行為,該語句的具體行為由編譯器來自行決定如何處理。對于這種未定義行為的語句我們應該盡量予以避免!
接着來看下面的例子:
#include<iostream>
using namespace std;
const int * Search(const int * a, int n, int val);
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int val = 5;
int *p;
p = const_cast<int *>(Search(a, 10, val));
if(p == NULL)
cout<<"Not found the val in array a"<<endl;
else
cout<<"hvae found the val in array a and the val = "<<*p<<endl;
return 0;
}
const int * Search(const int * a, int n, int val)
{
int i;
for(i=0; i<n; i++)
{
if(a[i] == val)
return &a[i];
}
return NULL;
}
定義了一個函數,用于在a數組中尋找val值,如果找到了就傳回該值的位址,如果沒有找到則傳回NULL。函數Search傳回值是const指針,當我們在a數組中找到了val值的時候,我們會傳回val的位址,最關鍵的是a數組在main函數中并不是const,是以即使我們去掉傳回值的常量性有可能會造成a數組被修改,但是這也依然是安全的。
對于引用,我們同樣能使用const_cast來強制去掉常量性:
#include<iostream>
using namespace std;
const int & Search(const int * a, int n, int val);
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int val = 5;
int &p = const_cast<int &>(Search(a, 10, val));
if(p == NULL)
cout<<"Not found the val in array a"<<endl;
else
cout<<"hvae found the val in array a and the val = "<<p<<endl;
return 0;
}
const int & Search(const int * a, int n, int val)
{
int i;
for(i=0; i<n; i++)
{
if(a[i] == val)
return a[i];
}
return NULL;
}
了解了const_cast的使用場景後,可以知道使用const_cast通常是一種無奈之舉,同時在今後的C++程式設計過程中一定不要利用const_cast去掉指針或引用的常量性并且去修改原始變量的數值,這是一種非常不好的行為。
reinterpret_cast
int *a = new int;
double *d = reinterpret_cast<double *>(a);
dynamic_cast