C++類型轉換(翻譯自cplusplus)

openkk 12年前發布 | 4K 次閱讀 ArtistX

前言

  原文翻譯自http://www.cplusplus.com/doc/tutorial/typecasting/,覺得這篇文章講C++類型轉換簡單明了,所以特別翻譯了下。

  在C++中,將一個已知的類型轉換為另一個類型,我們稱呼為類型轉換,本文會介紹C++的各種類型轉換。

隱式轉換

隱式轉換不需要任何操作符,它們會自動執行,當值被賦值到兼容類型,就會執行,例如:

short a=2000;int b;
b=a;

隱式轉換,也包括構造函數和運算符的轉換,例如:

class A {};class B { public: B (A a) {} };

A a;
B b=a;

 

顯式轉換

C++是一個強類型的語言。許多轉換,需要顯式轉換,例如

short a=2000;int b;
b = (int) a;    // c-like cast notation b = int (a);    // functional notation

 

上述的類型轉換已經滿足了基本類型的轉換了,但是如果應用于類和指針中,代碼可以編譯,但是在運行過程中會出錯。例如

// class type-casting #include <iostream>using namespace std;class CDummy {
    float i,j;
};class CAddition {
    int x,y;
  public:
    CAddition (int a, int b) { x=a; y=b; }
    int result() { return x+y;}
};int main () {
  CDummy d;
  CAddition * padd;
  padd = (CAddition*) &d;
  cout << padd->result();
  return 0;
}

這段代碼會在運行期出錯,在執行padd->result()時異常退出。

傳統明確的類型轉換可以轉換成任何其他指針類型任何指針它們指向類型無關在隨后的調用成員的結果會產生一個運行時錯誤或意外的結果


C++標準轉換運算符

傳統的類和指針的類型轉換,十分不安全,可能會在運行時,由于類型不匹配異常退出,所以C++提供了四個標準轉換運算符:dynamic_cast, reinterpret_cast, static_cast, const_cast

dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)

 

dynamic_cast

dynamic_cast只能用于指針和引用的對象其目的是確保類型轉換結果是一個有效的完成所請求的類對象,所以當我們從一個類轉換到這個類的基類,dynamic_cast總是可以成功

class CBase { };class CDerived: public CBase { };

CBase b; CBase* pb;
CDerived d; CDerived* pd;

pb = dynamic_cast<CBase*>(&d);     // ok: derived-to-base pd = dynamic_cast<CDerived*>(&b);  // wrong: base-to-derived

當新的類型不是被轉換的類型的基類,dynamic_cast無法完成指針的轉換,返回NULL,如果dynamic_cast是用來轉換為引用類型的轉換失敗,會拋出"Bad_cast exception"異常。

dynamic_cast 可以轉換NULL指針為不相關的類,也可以任何類型的指針為void指針。 

dynamic_cast的需要運行時類型信息(RTTI)保持動態類型跟蹤一些編譯器支持此功能默認情況下是禁用選項必須啟用運行時類型檢查使用dynamic_cast的正常工作


static_cast

static_cast可以執行相關的類指針之間轉換不僅從派生類到基類的轉換,也可以做到基類到派生類的轉換。static_cast沒有在運行時進行安全檢查,因此,它是程序員,以確保轉換是安全的,但是dynamic_cast的類型安全檢查開銷,static_cast是可以避免的。

class CBase {};class CDerived: public CBase {};
CBase * a = new CBase;
CDerived * b = static_cast<CDerived*>(a);


上述代碼是合法的,雖然b指向一個不完整的對象,并可能在運行期導致錯誤。

static_cast也可以用來執行任何其他非指針的轉換例如像基本類型之間標準轉換也可以隱式執行

double d=3.14159265;int i = static_cast<int>(d); 


reinterpret_cast

reinterpret_cast轉換成任何其他指針類型甚至無關的類任何指針類型操作的結果是一個簡單一個指針到其他二進制拷貝所有指針轉換是允許的:不管是指針指向的內容還是指針本身的類型。

同時,它也可以把指針轉換為整數,但是整數是平臺相關的,必須保證整數足夠大到可以包含指針本身的內容,最后再轉換為一個合法的指針。

class A {};class B {};
A * a = new A;
B * b = reinterpret_cast<B*>(a)


const_cast

const_cast用于操縱對象的常量性設置刪除例如,一個函數要求一個非const參數,而程序需要傳遞一個const參數。

#include <iostream>using namespace std;void print (char * str)
{
  cout << str << endl;
}int main () {
  const char * c = "sample text";
  print ( const_cast<char *> (c) );
  return 0;
}


typeid

typeid的允許檢查表達式的類型
typeid (expression)


這個操作符返回一個引用標準頭文件<typeinfo>定義常量對象一個類型的type_info這個返回值可以與另一個使用運算符==和!=進行比較兩個數據類型或類的名稱,或者也可以使用其name() 成員函數獲得類型名字(一個0結束的字符串)。

// typeid #include <iostream>
#include <typeinfo>using namespace std;int main () {
  int * a,b;
  a=0; b=0;
  if (typeid(a) != typeid(b))
  {
    cout << "a and b are of different types:\n";
    cout << "a is: " << typeid(a).name() << '\n';
    cout << "b is: " << typeid(b).name() << '\n';
  }
  return 0;
}

typeid應用使用RTTI來跟蹤動態對象類型,那么typeid的應用于表達式,其類型是一個多態,其結果是派生的最完整的對象類型

// typeid, polymorphic class #include <iostream>
#include <typeinfo>
#include <exception>using namespace std;class CBase { virtual void f(){} };class CDerived : public CBase {};int main () {
  try {
    CBase* a = new CBase;
    CBase* b = new CDerived;
    cout << "a is: " << typeid(a).name() << '\n';
    cout << "b is: " << typeid(b).name() << '\n';
    cout << "*a is: " << typeid(*a).name() << '\n';
    cout << "*b is: " << typeid(*b).name() << '\n';
  } catch (exception& e) { cout << "Exception: " << e.what() << endl; }
  return 0;
}

注意返回的字符串成員的type_info名稱取決于你的編譯器具體實現,典型類型名稱,它不一定是一個簡單的字符串.

如果類型typeid的參數引用操作符(*)開頭的指針,而且這個指針是NULLtypeid會拋出一個bad_typeid異常

轉自:http://www.cnblogs.com/ggjucheng/archive/2012/01/04/2311650.html

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!