天天看點

C++強制類型轉換

在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

繼續閱讀