再谈C++类型转换
1. dynamic_cast
? ? ? 僅在運行時,根據待轉換類中虛表中的類的信息進行判斷,是否能轉換成功。所以,只要待轉換對象有虛表,就可以編譯通過,否則,編譯錯誤。
?指針轉換失敗返回NULL, 引用轉換失敗則要拋出異常。
? ? ? 可以用于類層次之間的上行轉換和下行轉換,還可以用于類之間的交叉轉換。
在類層次間進行上行轉換時,dynamic_cast和static_cast的效果是一樣的;在進行下行轉換時,dynamic_cast具有類型檢查的功能,比static_cast更安全。
并且比static_cast多了一項類之間交叉轉換的功能。
以上可以作為dynamic_cast特有的使用場景??梢哉fdynamic_cast僅能用于多態類的轉換。
? ?下面的例子:
class A {public: virtual void f(){}}; class B {public: virtual void g(){}}; class AB: public virtual A, public B {}; class C{};int main() { AB ab;C *pc = dynamic_cast<C*>(&ab);//只要原類中有虛表,用dynamic_cast就能編譯通過if (pc == NULL)cout<<"pc is null"<<endl;cout<<"ab addr "<<&ab<<endl;B* bp =dynamic_cast<B*>(&ab); // 向上轉cout<<"bp addr "<<bp<<endl;A* ap = dynamic_cast<A*>(&ab); //cout<<"ap addr "<<ap<<endl;AB& abr = dynamic_cast<AB&>(*bp); // 向下轉cout<<"abr addr "<<&abr<<endl;ap = dynamic_cast<A*>(bp); assert(ap!= NULL);//交叉轉bp = dynamic_cast<B*>(ap); assert(bp!= NULL);//交叉轉ap = dynamic_cast<A*>(&abr); assert(ap!= NULL);bp = dynamic_cast<B*>(&abr); assert(bp!= NULL);cout<<"succeed"<<endl;return 0; }
2. static_cast
? ??
1、用于類層次結構中基類和子類之間指針或引用的轉換。進行上行轉換(把子類的指針或引用轉換成基類表示)是安全的;
進行下行轉換(把基類指針或引用轉換成子類表示)時,由于沒有動態類型檢查,所以是不安全的。
2、用于基本數據類型之間的轉換,如把int轉換成char,把int轉換成enum。這種轉換的安全性也要開發人員來保證。
3、把空指針轉換成目標類型的空指針。
4、把任何類型的表達式轉換成void類型。
5、增加指針或者引用的const屬性
注意:static_cast不能轉換掉expression_r_r的const、volitale、或者__unaligned屬性。
3. const_cast
運算符用來修改(添加/刪除)類型的const或volatile屬性
常量指針被轉化成非常量指針,并且仍然指向原來的對象;常量引用被轉換成非常量引用,并且仍然指向原來的對象;常量對象被轉換成非常量對象。
?
注意如下代碼:
const int constant = 21;
const int* const_p = &constant;
int* modifier = const_cast<int*>(const_p);
*modifier = 7;
?
輸出結果:
cout?<<"constant: "<< constant <<endl;
cout?<<?"const_p: "<< *const_p <<endl;
cout?<<?"modifier: "<< *modifier <<endl;
/**
constant: 21
const_p: 7
modifier: 7
**/
?
cout?<<?"constant: "<< &constant <<endl;
cout?<<?"const_p: "<< const_p <<endl;
cout?<<?"modifier: "<< modifier <<endl;
/**
constant: 0x7fff5fbff72c
const_p: 0x7fff5fbff72c
modifier: 0x7fff5fbff72c
**/
?
三者的地址是一樣的,但是值卻不一樣,說明c++里面,const就是const,const有他存在的意義。
IBM的C++指南稱呼“*modifier = 7;”為“未定義行為(Undefined Behavior)”。所謂未定義,是說這個語句在標準C++中沒有明確的規定,由編譯器來決定如何處理。
因此對于const所修飾的數據,我們絕對不對他們重新賦值。
那么什么時候需要用到const_cast呢?
1、我們可能調用了一個參數不是const的函數,而我們要傳進去的實際參數確實const的,但是我們知道這個函數是不會對參數做修改的。于是我們就需要使用const_cast去除const限定,以便函數能夠接受這個實際參數。
2、我們定義了一個非const的變量,但用帶const限定的指針去指向它,在某一處我們突然又想修改了,可是我們手上只有指針,這時候我們可以去const來修改了。
4.reinterpret_cast
必須是一個指針、引用、算術類型、函數指針或者成員指針。
它可以把一個指針轉換成一個整數,也可以把一個整數轉換成一個指針(先把一個指針轉換成一個整數,
在把該整數轉換成原類型的指針,還可以得到原先的指針值)。
reinterpret_cast可以轉換任意一個32bit整數,包括所有的指針和整數??梢园讶魏握麛缔D成指
針,也可以把任何指針轉成整數,以及把指針轉化為任意類型的指針,威力最為強大!但不能將非32bit的實例轉成指針。
總之,只要是32bit的東東,怎么轉都行!?
int aa = reinterpret_cast<int>(&ab);//ok
A aa = reinterpret_cast<A>(ab);// error。不能用于對象的轉換,但是可以用對象指針和引用的轉換
??
總結
- 上一篇: 从三个数组中选择满足条件的三个数
- 下一篇: 链接二叉树中同一层的节点