1. 程式人生 > 其它 >4-11.3 C++中的顯式類轉換

4-11.3 C++中的顯式類轉換

目錄

static_cast

1.用來改變基本型別:一般是高精度轉低精度

顯示地告訴程式閱讀者和編譯器,不考慮高精度想低精度轉換時造成的精度損失

#include<iostream>
using namespace std;
int main(){
    double d = 2.1;
    int i = 6;
    int res = i/d;  //i被隱式地轉換為double res=6/2.1 = 2
    cout<<res<<endl;  //輸出2
    res = i/static_cast<int>(d); //d被強制轉換為int res = 6/2 = 3
    cout<<res<<endl;  //輸出3
    return 0;
}

2.恢復void* 指標型別

#include<iostream>
using namespace std;
int main(){
    int i = 2;
    void *p = &i;  //無法通過p得到它所指物件的值
    int *q = static_cast<int*>(p);  //將其轉換為int*,得到其所指向的值
    cout<<*q<<endl;  //輸出2
    return 0;
}

注意:void*在強制型別轉換時只能轉換為原來的對應型別,如例子中,只能轉換為int*,否則會產生未定義行為

const_cast

用來去除底層const(low-level const)

#include<iostream>
using namespace std;
int main(){
    const char *pc;
    char *p = const_cast<char*>(pc);  //把pc的底層const去除,否則無法對p進行初始化(p不是const)
    int *ip = static_cast<int*>( const_cast<char*>(pc)); //去除const後再改變基本型別
    return 0;
}

注:1.const_cast可以去除底層const,但不代表轉換後的指標可以改變其指向的值,如果*p是一個const物件,依然不能用p改變其值

2.const_cast只能去除const,不能改變物件的原型別,const_cast<string>(pc);是不行的,改用static_const<string>(pc);

const_cast在函式過載時運用廣泛

reinterpret_cast

為運算物件的位模式提供較低層次的重新解釋,但並不真正改變物件型別

#include<iostream>
using namespace std;
int main(){
    int *ip;
    char *pc = reinterpret_cast<char*>(ip);  //pc所指的真實物件實際上是int型別而不是字元
    string s(pc);  //用int*來初始化string顯然會出現問題,但由於有顯示型別轉換,所以編譯器不會報錯
    cout<<s<<endl;
    return 0;
}

使用reinterpret_cast是非常危險的,用pc初始化str的例子很好地證明了這一點。其中的關鍵問題是型別改變了,但編譯器沒有給出任何警告或者錯誤的提示資訊。當我們用一個int的地址初始化pc時,由於顯式地聲稱這種轉換合法,所以編譯器不會發出任何警告或錯誤資訊。接下來再使用pc時就會認定它的值是char*型別,編譯器沒法知道它實際存放的是指向int的指標。最終的結果就是,在上面的例子中雖然用pc初始化 str 沒什麼實際意義,甚至還可能引發更糟糕的後果,但僅從語法上而言這種操作無可指摘。查詢這類問題的原因非常困難,如果將ip 強制轉換成pc的語句和用pc初始化 string物件的語句分屬不同檔案就更是如此。

所以在程式設計時經歷避免強制型別轉換

舊式型別轉換

(type)expr:c語言風格的函式型別轉換,其含義並不清晰,根據語境會分別具有static\_castconst\_castreinterpret\_cast的功能。

int *ip;
char *pc = (char*)ip;  //作用同reinterpret_cast

所以追蹤錯誤時會更加困難,不建議使用。