日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++四种强制类型转换 dynamic_cast,const_cast,static_cast,reinterpret_cast

發(fā)布時(shí)間:2024/2/28 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++四种强制类型转换 dynamic_cast,const_cast,static_cast,reinterpret_cast 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
綜述
  • dynamic_cast? 用于多態(tài)類型的轉(zhuǎn)換

  • static_cast?用于非多態(tài)類型的轉(zhuǎn)換

  • const_cast? 用于刪除?constvolatile?和?__unaligned?特性

  • reinterpret_cast?用于位的簡(jiǎn)單重新解釋

static_cast

用法:static_cast < type-id > ( expression_r_r )

該運(yùn)算符把expression_r_r轉(zhuǎn)換為type-id類型,但沒(méi)有運(yùn)行時(shí)類型檢查來(lái)保證轉(zhuǎn)換的安全性。它主要有如下幾種用法:
用于類層次結(jié)構(gòu)中基類和子類之間指針或引用的轉(zhuǎn)換。進(jìn)行上行轉(zhuǎn)換(把子類的指針或引用轉(zhuǎn)換成基類表示)是安全的;進(jìn)行下行轉(zhuǎn)換(把基類指針或引用轉(zhuǎn)換成子類表示)時(shí),由于沒(méi)有動(dòng)態(tài)類型檢查,所以是不安全的。
用于基本數(shù)據(jù)類型之間的轉(zhuǎn)換,如把int轉(zhuǎn)換成char,把int轉(zhuǎn)換成enum。這種轉(zhuǎn)換的安全性也要開(kāi)發(fā)人員來(lái)保證。
把空指針轉(zhuǎn)換成目標(biāo)類型的空指針。
把任何類型的表達(dá)式轉(zhuǎn)換成void類型。
注意:static_cast不能轉(zhuǎn)換掉expression_r_r的const、volitale、或者_(dá)_unaligned屬性。

dynamic_cast

用法:dynamic_cast < type-id > ( expression_r_r )

該運(yùn)算符把expression_r_r轉(zhuǎn)換成type-id類型的對(duì)象。Type-id必須是類的指針、類的引用或者void *;如果type-id是類指針類型,那么expression_r_r也必須是一個(gè)指針,如果type-id是一個(gè)引用,那么expression_r_r也必須是一個(gè)引用。

dynamic_cast主要用于類層次間的上行轉(zhuǎn)換和下行轉(zhuǎn)換,還可以用于類之間的交叉轉(zhuǎn)換。

在類層次間進(jìn)行上行轉(zhuǎn)換時(shí),dynamic_cast和static_cast的效果是一樣的;在進(jìn)行下行轉(zhuǎn)換時(shí),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指向一個(gè)D類型的對(duì)象,pd1和pd2是一樣的,并且對(duì)這兩個(gè)指針執(zhí)行D類型的任何操作都是安全的;但是,如果pb指向的是一個(gè) B類型的對(duì)象,那么pd1將是一個(gè)指向該對(duì)象的指針,對(duì)它進(jìn)行D類型的操作將是不安全的(如訪問(wèn)m_szName),而pd2將是一個(gè)空指針。另外要注意:B要有虛函數(shù),否則會(huì)編譯出錯(cuò);static_cast則沒(méi)有這個(gè)限制。這是由于運(yùn)行時(shí)類型檢查需要運(yùn)行時(shí)類型信息,而這個(gè)信息存儲(chǔ)在類的虛函數(shù)表(關(guān)于虛函數(shù)表的概念,詳細(xì)可見(jiàn)<Inside c++ object model>)中,只有定義了虛函數(shù)的類才有虛函數(shù)表,沒(méi)有定義虛函數(shù)的類是沒(méi)有虛函數(shù)表的。

另外,dynamic_cast還支持交叉轉(zhuǎn)換(cross cast)。如下代碼所示。

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); //copile error

D *pd2 = dynamic_cast<D *>(pb); //pd2 is NULL

delete pb;

}

在函數(shù)foo中,使用static_cast進(jìn)行轉(zhuǎn)換是不被允許的,將在編譯時(shí)出錯(cuò);而使用 dynamic_cast的轉(zhuǎn)換則是允許的,結(jié)果是空指針。

reinpreter_cast

用法:reinpreter_cast<type-id> (expression_r_r)

type-id必須是一個(gè)指針、引用、算術(shù)類型、函數(shù)指針或者成員指針。它可以把一個(gè)指針轉(zhuǎn)換成一個(gè)整數(shù),也可以把一個(gè)整數(shù)轉(zhuǎn)換成一個(gè)指針(先把一個(gè)指針轉(zhuǎn)換成一個(gè)整數(shù),在把該整數(shù)轉(zhuǎn)換成原類型的指針,還可以得到原先的指針值)。

該運(yùn)算符的用法比較多。

const_cast

用法:const_cast<type_id> (expression_r_r)

該運(yùn)算符用來(lái)修改類型的const或volatile屬性。除了const 或volatile修飾之外, type_id和expression_r_r的類型是一樣的。

常量指針被轉(zhuǎn)化成非常量指針,并且仍然指向原來(lái)的對(duì)象;常量引用被轉(zhuǎn)換成非常量引用,并且仍然指向原來(lái)的對(duì)象;常量對(duì)象被轉(zhuǎn)換成非常量對(duì)象。

Voiatile和const類試。舉如下一例:

class B

{

public:

int m_iNum;

}

void foo()

{

const B b1;

b1.m_iNum = 100; //comile error

B b2 = const_cast<B>(b1);

b2. m_iNum = 200; //fine
}

上面的代碼編譯時(shí)會(huì)報(bào)錯(cuò),因?yàn)閎1是一個(gè)常量對(duì)象,不能對(duì)它進(jìn)行改變;使用const_cast把它轉(zhuǎn)換成一個(gè)常量對(duì)象,就可以對(duì)它的數(shù)據(jù)成員任意改變。注意:b1和b2是兩個(gè)不同的對(duì)象。

最容易理解的解釋:

???dynamic_cast: ??通常在基類和派生類之間轉(zhuǎn)換時(shí)使用;
???const_cast: ??主要針對(duì)const和volatile的轉(zhuǎn)換.???
???static_cast: ??一般的轉(zhuǎn)換,如果你不知道該用哪個(gè),就用這個(gè)。???
???reinterpret_cast: ??用于進(jìn)行沒(méi)有任何關(guān)聯(lián)之間的轉(zhuǎn)換,比如一個(gè)字符指針轉(zhuǎn)換為一個(gè)整形數(shù)。




1、dynamic_cast運(yùn)算符 該轉(zhuǎn)換符用于將一個(gè)指向派生類的基類指針或引用轉(zhuǎn)換為派生類的指針或引用 注意:dynamic_cast轉(zhuǎn)換符只能用于含有虛函數(shù)的類,其表達(dá)式為?dynamic_cast<類型>(表達(dá)式) 其中的類型是指把表達(dá)式要轉(zhuǎn)換成的目標(biāo)類型,比如含有虛函數(shù)的基類B和從基類B派生出的派生類D,則: B *pb;? D *pd, md; ? pb = &md;? pd = dynamic_cast<D *>(pb);? 最后一條語(yǔ)句表示把指向派生類D的基類指針pb轉(zhuǎn)換為派生類D的指針,然后將這個(gè)指針賦給派生類D的指針pd,有人可能會(huì)覺(jué)得這樣做沒(méi)有意義,既然指針pd要指向派生類為什么不pd = &md;這樣做更直接呢?有些時(shí)候我們需要強(qiáng)制轉(zhuǎn)換,比如如果指向派生類的基類指針B想訪問(wèn)派生類D中的除虛函數(shù)之外的成員時(shí)就需要把該指針轉(zhuǎn)換為指向派生類D的指針,以達(dá)到訪問(wèn)派生類D中特有的成員的目的,比如派生類D中含有特有的成員函數(shù)g(),這時(shí)可以這樣來(lái)訪問(wèn)該成員dynamic_cast<D *>(pb)->g();因?yàn)閐ynamic_cast轉(zhuǎn)換后的結(jié)果是一個(gè)指向派生類的指針,所以可以這樣訪問(wèn)派生類中特有的成員。但是該語(yǔ)句不影響原來(lái)的指針的類型,即基類指針pb仍然是指向基類B的。如果單獨(dú)使用該指針仍然不能訪問(wèn)派生類中特有的成員。一般情況下不推見(jiàn)這樣使用dynamic_cast轉(zhuǎn)換符,因?yàn)閐ynamic_cast的轉(zhuǎn)換并不會(huì)總是成功的,具體情況在后面介紹。
dynamic_cast的注意事項(xiàng) dynamic_cast轉(zhuǎn)換符只能用于指針或者引用。dynamic_cast轉(zhuǎn)換符只能用于含有虛函數(shù)的類。dynamic_cast轉(zhuǎn)換操作符在執(zhí)行類型轉(zhuǎn)換時(shí)首先將檢查能否成功轉(zhuǎn)換,如果能成功轉(zhuǎn)換則轉(zhuǎn)換之,如果轉(zhuǎn)換失敗,如果是指針則反回一個(gè)0值,如果是轉(zhuǎn)換的是引用,則拋出一個(gè)bad_cast異常,所以在使用dynamic_cast轉(zhuǎn)換之間應(yīng)使用if語(yǔ)句對(duì)其轉(zhuǎn)換成功與否進(jìn)行測(cè)試,比如pd = dynamic_cast(pb); if(pd){…}else{…},或者這樣測(cè)試if(dynamic_cast(pb)){…}else{…}
因此,dynamic_cast操作符一次執(zhí)行兩個(gè)操作。首先驗(yàn)證被請(qǐng)求的轉(zhuǎn)換是否有效,只有轉(zhuǎn)換有效,操作符才實(shí)際進(jìn)行轉(zhuǎn)換。基類的指針可以賦值為指向派生類的對(duì)象,同樣,基類的引用也可以用派生類對(duì)象初始化,因此,dynamic_cast操作符執(zhí)行的驗(yàn)證必須在運(yùn)行時(shí)進(jìn)行。
2、const_cast操作符 其表達(dá)式為?const_cast<類型>(表達(dá)式)
其中類型指要把表達(dá)式轉(zhuǎn)換為的目標(biāo)類型。該操作符用于改變const和volatile,const_cast最常用的用途就是刪除const屬性,如果某個(gè)變量在大多數(shù)時(shí)候是常量,而在某個(gè)時(shí)候又是需要修改的,這時(shí)就可以使用const_cast操作符了。 const_cast操作符不能改變類型的其他方面,他只能改變const或volatile,即const_cast不能把int改變?yōu)閐ouble,但可以把const int改變?yōu)閕nt。const_cast只能用于指針或引用。
const_cast的用法舉例 比如:int a=3; const int *b=&a; int* c=const_cast(b); *c=4; cout<<a<<*c;這時(shí)輸出兩個(gè)4,如果不使用const_cast轉(zhuǎn)換符則常量指針*c的值是不能改變的,在這里使用const_cast操作符,通過(guò)指針b就能改變常量指針和變量a的值。
3、static_cast操作符 該操作符用于非多態(tài)類型的轉(zhuǎn)換,任何標(biāo)準(zhǔn)轉(zhuǎn)換都可以使用他,即static_cast可以把int轉(zhuǎn)換為double,但不能把兩個(gè)不相關(guān)的類對(duì)象進(jìn)行轉(zhuǎn)換,比如類A不能轉(zhuǎn)換為一個(gè)不相關(guān)的類B類型。static_cast本質(zhì)上是傳統(tǒng)c語(yǔ)言強(qiáng)制轉(zhuǎn)換的替代品。
static_cast(靜態(tài)轉(zhuǎn)換)執(zhí)行非多態(tài)的轉(zhuǎn)換,用于代替C中通常的轉(zhuǎn)換操作。因此,被做為隱式類型轉(zhuǎn)換使用。顯式告訴編譯器,不關(guān)心轉(zhuǎn)換后精度損失。比如:int i;float f = 166.7f;i = static_cast<int>(f);此時(shí)結(jié)果,i的值為166。
4、reinterpret_cast操作符 該操作符用于將一種類型轉(zhuǎn)換為另一種不同的類型,比如可以把一個(gè)整型轉(zhuǎn)換為一個(gè)指針,或把一個(gè)指針轉(zhuǎn)換為一個(gè)整型,因此使用該操作符的危險(xiǎn)性較高,一般不應(yīng)使用該操作符。
reinterpret_cast(重述轉(zhuǎn)換)主要是將數(shù)據(jù)從一種類型的轉(zhuǎn)換為另一種類型。所謂“通常為操作數(shù)的位模式提供較低層的重新解釋”也就是說(shuō)將數(shù)據(jù)以二進(jìn)制存在形式的重新解釋。比如: int i;char *p = "This is a example.";i = reinterpret_cast<int>(p);此時(shí)結(jié)果,i與p的值是完全相同的。reinterpret_cast的作用是說(shuō)將指針p的值以二進(jìn)制(位模式)的方式被解釋為整型,并賦給i,一個(gè)明顯的現(xiàn)象是在轉(zhuǎn)換前后沒(méi)有數(shù)位損失,即一定不改變?cè)獢?shù)據(jù)。?

關(guān)于reinterpret_cast,使用這個(gè)操作符的類型轉(zhuǎn)換,其的轉(zhuǎn)換結(jié)果幾乎都是執(zhí)行期定義(implementation-defined)。因此,使用reinterpret_casts的代碼很難移植。?

reinterpret_casts的最普通的用途就是在函數(shù)指針類型之間進(jìn)行轉(zhuǎn)換。例如,假設(shè)你有一個(gè)函數(shù)指針數(shù)組

typedef void (*FuncPtr)(); // FuncPtr是一個(gè)指向函數(shù)的指針,該函數(shù)沒(méi)有參數(shù)返回值類型為void

FuncPtr funcPtrArray[10]; // funcPtrArray是一個(gè)能容納10個(gè)FuncPtrs指針的數(shù)組?


讓我們假設(shè)你希望(因?yàn)槟承┠涿畹脑?#xff09;把一個(gè)指向下面函數(shù)的指針存入funcPtrArray數(shù)組:

int doSomething();


你不能不經(jīng)過(guò)類型轉(zhuǎn)換而直接去做,因?yàn)閐oSomething函數(shù)對(duì)于funcPtrArray數(shù)組來(lái)說(shuō)有一個(gè)錯(cuò)誤的類型。在FuncPtrArray數(shù)組里的函數(shù)返回值是void類型,而doSomething函數(shù)返回值是int類型。

funcPtrArray[0] ?= ?&doSomething;?// 錯(cuò)誤!類型不匹配reinterpret_cast可以讓你迫使編譯器以你的方法去看待它們

funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething);?// this compiles?

?

轉(zhuǎn)換函數(shù)指針的代碼是不可移植的(C++不保證所有的函數(shù)指針都被用一樣的方法表示),在一些情況下這樣的轉(zhuǎn)換會(huì)產(chǎn)生不正確的結(jié)果。

總結(jié)

以上是生活随笔為你收集整理的C++四种强制类型转换 dynamic_cast,const_cast,static_cast,reinterpret_cast的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。