c/c++類型轉換相關總結
在c語言中存在兩種類型轉換:顯式類型轉換和隱式類型轉換;
顯示類型轉換:在類型前加上(type)變量,對變量進行的轉換,程序員自己顯式添加;
char *ptra = (char*)ptrb;
void *ptrc = (void*)ptrd;
隱式轉換:不同數據結構之間賦值和運算,函數調用傳遞參數時,編譯器自動完成;
char ch = 0;
int i = ch;
在c++中的類型轉換:
通過上面兩種方式,c語言中大部分的類型轉換都是以順利進行。至於能不能進行轉換,轉換後的結果如何,編譯器不管,需要用戶自己去控制。
c++繼承了c中的隱式和顯式轉換的方式。但是這種轉換並不是安全和嚴格的,加上c++本身對象模型的復雜性,c++增加了四個顯示轉換的關鍵字。(c++是強類型語言)
(static_cast,dynamic_cast,const_static,reinterpret_cast)
1、static_cast
用法:static_cast<type-id>(exdivssion)
該運算符把exdivssion轉換為type-id類型,但沒有運行時類型檢查來保證轉換的安全性。
它主要有如下幾種用法:
1)用於類層結構中基類和子類之間指針或引用的轉換。
進行上行轉換是安全的。(把子類的指針或引用轉換為基類表示)
進行下行轉換時,由於沒有動態類型檢查,所以是不安全的。(把基類指針或引用轉換成子類表示)
2)用於基本數據類型之間的轉換,如把int轉換成char,把int轉換成enum,這種轉換的安全性也要開發人員來保證。
3)把空指針轉換成目標類型的空指針。
4)把任何類型的表達式轉換成void類型。
註意:static_cast不能替換掉exdivssion的const、volitale、或者unaligned屬性。
2、dynamic_cast
用法:dynamic_cast<type-id>(exdivssion)
該運算符把exdivssion轉換成tepe-id類型的對象。type-id必須是類的指針、類的引用或者void*;
如果type-id是類指針類型,那麽exdivssion也必須是一個指針,如果type-id是一個引用,那麽exdivssion也必須是一個引用。
dynamic_cast主要用於類層次間的上行轉換和下行轉換,還可以用於類之間的交叉轉換。
在類層次進行上行轉換時,dynamix_cast和static_cast的效果是一樣的;在進行下行轉換時,dynamic_cast具有類型檢查的功能,比static_cast更安全。
class B{
public:
int m_inum;
virtual void foo();
};
class D :public B{
public:
char *m_szname[100];
};
void func(B *pb){
D* pd1 = static_cast<D*>(pb);
D* pd2 = dynamic_cast<D*>(pb);
}
在上面的代碼中,如果pb只想一個D類型的對象,pd1和pd2是一樣的,並且對這兩個指針執行D類型的任何操作都是安全的;但是,如果pb指向的是一個B類型的對象,那麽pd1將是一個指向該對象的指針,對他進行D類型的操作將是不安全的(如訪問m_szname),而pd2將是一個空指針。
另外要註意:dynamic_cast轉換對象時被轉換對象類型必須是多態類型,即被轉換對象必須公有繼承自其他類,或其擁有虛函數。即B要有虛函數,否則會編譯錯誤;static_cast則沒有這個限制,這是由於運行時類型檢查需要運行時類型信息,而這個信息存儲在累的虛函數表中,只有定義了虛函數的類才有虛函數表,沒有定義虛函數的類是沒有虛函數表的。
另外,dynamic_cast還支持交叉轉換(crosscast)。如下代碼所示。
class A{
public:
int m_inum;
virtual void f(){};
};
class B:public A{};
class D:public A{};
void foo(){
B *pb = new B;
pb->m_inum = 100;
D *pd1 = static_cast<D>((pb)); //編譯錯誤;
D *pd1 = dynamic_cast<D>((pb));
delete pb;
}
在函數foo中,使用static_cast進行轉換是不被允許的,將在編譯時出錯;而使用dynamic_cast的轉換則是允許的,結果是空指針;
c/c++類型轉換相關總結