c++ 強制類型轉換

前言

在c語言中學的強制轉換是用()來實現的; 而在c++中更多的是用case-name系列的關鍵字來告訴編譯器咱們須要轉換的類型. c++引入這些關鍵字也是爲了看代碼的時候清晰明瞭, 每一個關鍵字都有指定的功能. 下面咱們就來分析這些關鍵字.c++

case-name關鍵字

1. static_cast

在編譯期間完成類型轉換.安全

a. 將原有的自動類型轉換 , 如 : short轉爲int, int轉爲double, 非const轉爲const類型函數

short sh;
int i = static_cast<int>(sh);
const int ci = static_cast<const int>(i);

b. void 指針和具體類型指針之間的轉換 this

void *vp;
int *ip = static_cast<int*>(vp);

c. 有轉換構造函數或者類型轉換函數的類與其它類型之間的轉換指針

如 : A是B的基類code

B *b;
A *a = static_cast<A *>(b); // 這種建議使用dynamic_cast來轉換

不能用於無關類型之間的轉換 , 如 : int* 轉爲double* 等對象

int *pi;
double *di = static_cast<double *>(pi); // error

2. const_cast

const_cast (經常使用於函數的重載) 常量指針(引用)被轉化成很是量指針(引用),而且仍然指向原來的對象繼承

顧名思義, const_cast就是在咱們須要修改const修飾的常量的時候用.ip

const int ci = 1;
int *p = const_cast<int*>(&ci);
*p = 10;

cout << &ci << " " << p << endl;    // 0x7ffd856729cc 0x7ffd856729cc
cout << ci << endl; // 1
cout << *p << endl; // 10

注意 : 上面的ci的值最終仍是沒有被修改, 這就是後半句 : 仍然指向原來的對象. 咱們只能經過const_cast忽略對象的屬性, 卻依然不能修改對象.ci

可能有人就認爲const_cast並無用, 可是咱們確實用int*指向了const int*了, 這是通常咱們都沒法作到的. 一樣, 下面還有const_cast可以作到的.

這有一部分的代碼, 咱們在重載const函數時, 經常會重複寫不少同樣的代碼, 而使用const_cast就能夠避免寫重複的代碼.

class A
{
public:
    ...
    const type& operator[](std::size_t size) const
    {
        return *(ar + size);
    }
    type& operator[](std::size_t size)
    {
        return const_cast<type &>(static_cast<const A&>(*this)[size]);
    }

private:
    ...
    std::size_t size;
    type * ar;
};

3. reinterpret_cast

reinterpret_cast這種轉換僅僅是對二進制位的從新解釋(修改), 不會藉助已有的轉換規則對數據進行調整, 很是簡單粗暴, 風險很高, 通常咱們不推薦使用.

可是既然c++規定了這中轉換, 那麼何時用合適?在IBM C++指南中明確說了

  • 從指針類型到一個足夠大的整數類型
  • 從整數類型或者枚舉類型到指針類型
  • 從一個指向函數的指針到另外一個不一樣類型的指向函數的指針
  • 從一個指向對象的指針到另外一個不一樣類型的指向對象的指針
  • 從一個指向類函數成員的指針到另外一個指向不一樣類型的函數成員的指針
  • 從一個指向類數據成員的指針到另外一個指向不一樣類型的數據成員的指針

總結來講:reinterpret_cast用在任意指針(或引用)類型之間的轉換;以及指針與足夠大的整數類型之間的轉換;從整數類型(包括枚舉類型)到指針類型,無視大小

就像下面這樣static_cast沒法作的但reinterpret_cast就能夠完成, 可是賦值等操做卻會運行時報錯, 這就是reinterpret_cast不安全之處, 它能讓代碼經過編譯, 操做時卻會報錯, 通常建議reinterpret_cast只有將轉換後的類型值轉換回到其原始類型來使用, 作一箇中間臨時轉存。

int *pi = NULL;
double *di = reinterpret_cast<double *>(pi);

4. dynamic_cast

dynamic_cast用於在類的繼承層次之間進行類型轉換, 它既容許向上轉型, 也容許向下轉型.

class A {};
class B : public A {};

向上轉型 : 基類指針(引用)指向子類指針(引用), 這樣的轉換是安全的.

B *b;
A *a = static_cast<A *>(b); 
A *ta = dynamic_cast<A *>(b);// 也可寫成這樣, 最好建議這樣轉換

向下轉型 : 藉助 RTTI 信息進行檢測, 肯定安全的才能轉換成功, 不然就轉換失敗, 有風險.

A *a;
B *b = dynamic_cast<B *>(a);

總結

雖然c語言的()強制能用, 可是最好推薦使用c++的轉化系列, 畢竟看代碼的時候很容易可以知道轉化對象和緣由, 也容易分析. 本片我將四種轉化儘可能寫的簡單, 多用實例證實, 只是但願可以快速的明瞭每一個的用法.

  1. static_cast : 有關聯的 對象之間可以進行轉化.
  2. const_cast : 忽略const/volatile修飾, 可是實際不會修改對象, 經常使用於重載
  3. dynamic_cast : 最多用於向下轉化, 但並不安全
  4. reinterpret_cast : 二進制間, 可無關聯對象間的轉化, 很是不安全.
相關文章
相關標籤/搜索