標籤:程式 void 定義 ptr 顯示 自動 表達 儲存 傳遞參數
在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)用於基礎資料型別 (Elementary Data Type)之間的轉換,如把int轉換成char,把int轉換成enum,這種轉換的安全性也要開發人員來保證。
3)把null 指標轉換成目標類型的null 指標。
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將是一個null 指標。
另外要注意: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的轉換則是允許的,結果是null 指標;
c/c++類型轉換相關總結