歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C++類型轉換

    類型轉換,顧名思義即將操作數轉化為所需要的類型。C++作為C語言的超集,完全繼承了C語言所具有的類型轉換方法與能力。C語言有兩種類型轉換方式:隱式轉換(implicit)和顯示轉換(explicit)。示例如下:

int a = 10;
double b = a;     // 隱式轉換
int c = (int)b;   // 顯示轉換

    容易看出,這兩種轉換方式存在某些缺陷,如意圖不夠明確,安全性得不到保證(尤其是對引進了class類型的C++語言)。因此,C++引進了4種類型轉換操作符(static_cast, const_cast, dynamic_cast, reinterpret_cast)以及標識符explicit。接下來我將對以上4個轉換操作符和1個標識符進行講解。

一、static_cast

    static_cast在C++中屬於較常使用的類型轉換符,與C語言的顯示轉換方式作用一樣,並且同樣沒有提供運行時類型安全檢查。使用這種轉換方式時需注意它不能將操作數的const、volatie等屬性移除。示例如下:

int m = 10;
const int n = 100;
double a = static_cast<double>(m);     // 等價於 a = (double) m ;
double b = static_cast<double>(n);     // 正確
double *c = static_cast<double*>(n);   // 錯誤, 必須在第一個double前加上const

二、const_cast

    此轉換可將操作數的const 或者 volatie 屬性移除而其他屬性不變(注意移除並不是指原常量就可以隨便更改,只是新賦值的變量才可以)。const_cast一般用於賦值指針或者引用。示例如下:

const int a = 10;
const int *pa = &a;              // const不能少,不能通過*pa改變a的值
int *b = const_cast<int *>(&a);  // 可以通過*b修改pa所指變量
*b = 20;
cout << a << " " << *pa << " " << *b << endl;

    cout的輸出結果為  10 20 20

補充知識:常量折疊

    編譯器進行語法分析時,會將常量或者常量表達式計算求值後替換表達式,並放入常量表。之後編譯器在優化的過程中會把碰見的const內容替換掉,假若遇到對常量的的取址或者外部聲明操作,則編譯器會在Data去為該常量分配一塊內存以使得相關操作合法。

    對於上例中的輸出,a在編譯階段就被會被替換成10。

三、dynamic_cast

      與static_cast剛好相反,dynamic_cast用於運行時檢查轉換是否安全,一般用於多態編程中父類、子類指針間的轉換。當其作用於子類升父類的轉換時,效果與static_cast一樣,反過來作用於父類指針到子類指針的下行轉換時其強大的功能便會凸顯。示例如下:

class A { public: int a;};
class B : public A{ public: double b; };class C : public A{ public: char c; };void JudgeType(A *a){
   if( dynamic_cast<B*>( a ) )  // 結果不為null即代表轉換成功
        cout << "此為B類" << endl;
   if( dynamic_cast<C*>( a ) )
        cout<< "此為C類" << endl;
   else
        cout<< "此為A類" << endl;
}

int main(){
  A*a = new A();
  A*b = new B();
  A*c = new C();
  JudgeType(a);// 輸出 “此為A類”
  JudgeType(b); // 輸出 “此為B類”
  JudgeType(c); // 輸出 “此為B類”
}

四、reinterpret_cast

      reinterpret中文譯為重新解釋,此變換在於將操作數的二進制形式數據重新解釋,如int轉換成char。此轉換通常帶來不可移植性,故使用場合較少。

五、explicit

    一般情況下若某個類的構造函數的傳入參數只有一個或者第二個參數開始都設置過默認參數,則實例化該類對象時可使用隱式變換方法,如下例main函數中的a對象和b對象。但有時這種隱式變換會導致某些預想不到的後果(非語法錯誤,只是有些內容復制不妥當等),這時我們就想阻止這種隱式變換,explicit關鍵字就派上用場了。

class A{
public:
    A(int id): Id(id){}
private:
   int Id;
};

class B{
public:
    B(int id, string nn = "XiaoMing"): Id(id), name(na){}
private:
   int Id;
   string name;
};

class C{
public:
   explicit C(int id): Id(id){}  // 添加explicit關鍵字,表明C對象只能進行顯示轉換
private:
   int Id;
};

int main(){
    A a= 12;    // 正確,12可以隱式轉換成A類型, 編譯器會隱式調用其構造函數
    B b = 34;    // 正確,34可以隱式轉換成B類型, 編譯器會隱式調用其構造函數
    C c1 = 45;    // 錯誤,不支持隱式轉換
    C c2 = C(45); // 正確,可進行顯示轉換
}

Copyright © Linux教程網 All Rights Reserved