在c++中提供瞭如下方式的類型轉換:
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
第二個轉換是錯誤的,除非基類是多態(polymorphic)。
當一個類是多態,dynamic_cast在運行時會執行一個特殊檢查,以確保表達式產生了一個有效的完整的對象:
// dynamic_cast
#include <iostream>
#include <exception>
using namespace std;
class CBase { virtual void dummy() {} };
class CDerived: public CBase { int a; };
int main () {
try {
CBase * pba = new CDerived;
CBase * pbb = new CBase;
CDerived * pd;
pd = dynamic_cast<CDerived*>(pba);
if (pd==0) cout << "Null pointer on first type-cast" << endl;
pd = dynamic_cast<CDerived*>(pbb);
if (pd==0) cout << "Null pointer on second type-cast" << endl;
} catch (exception& e) {cout << "Exception: " << e.what();}
return 0;
}
儘管兩者都是指針的類型CBase *,pba指向一個CDerived類型的對象,而從CDerived指向一個CBase類型的對象。因此,當他們各自的類型鑄件執行使用dynamic_cast,pba指向一個完整的CDerived類對象的類,而pbb指向一個不完整的CDerived類的對象。兼容性注意:dynamic_cast需要運行時類型信息(RTTI)跟蹤動態類型。一些編譯器支持這個特性作爲一個選項,默認情況下是禁用的。這必須啓用運行時類型檢查使用dynamic_cast正常工作。.
dynamic_cast也可以轉換空指針甚至不相關的類之間的指針,也可以把任何類型的指針轉換到空指針(void *)。
reinterpret_cast
reinterpret_cast可以完成從任何指針類型到任何其他指針類型的轉換,甚至是不相關的類。
由reinterpret_cast但不是static_cast的轉換在c++是低級操作,其解釋結果通常是系統相關的,因此不可移植的。
class A {};
class B {};
A * a = new A;
B * b = reinterpret_cast<B*>(a);
雖然b指向了一個不完整的對象,但是上面的語句是合法的,只不過,當b解引用可能時會產生運行時錯誤。static_cast
static_cast可以執行相關類指針之間的轉換,可以從派生類到基類,也可以從基類到派生類。這將確保至少類是兼容的,如果適當的對象被轉換,但是在運行時沒有執行安全檢查,以檢查是否被轉換的對象實際上是一個完整的對象類型的目的地。
因此,程序員,以確保轉換是安全的。但另一方面,dynamic_cast避免的類型安全檢查的開銷。
class CBase {};
class CDerived: public CBase {};
CBase * a = new CBase;
CDerived * b = static_cast<CDerived*>(a);
雖然b指向了一個不完整的對象,但是上面的語句是合法的,只不過,當b解引用可能時會產生運行時錯誤。
此外,static_cast還可以完成基本類型之間的轉換。但是不能轉換const, volatile, __unaligned等屬性。
const_cast
const_cast維護對象的常量屬性,可以設置或者去掉對象的常量屬性:
// const_cast
#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可以檢查變量的類型,並用name()加以輸出:
// 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;
}
參考:
[1] http://www.cplusplus.com/doc/tutorial/typecasting/
[2] http://msdn.microsoft.com/en-us/library/c36yw7x9%28v=vs.80%29.aspx