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

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

生活随笔

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

c/c++

C/C++ 之 C++强制类型转换(static_cast、dynamic_cast、const_cast、reinterpret_cast)

發(fā)布時(shí)間:2024/10/14 c/c++ 75 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C/C++ 之 C++强制类型转换(static_cast、dynamic_cast、const_cast、reinterpret_cast) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章轉(zhuǎn)載自:https://www.cnblogs.com/chenyangchun/p/6795923.html 。在了解這塊時(shí),發(fā)現(xiàn)了這篇文檔,感覺(jué)寫的很不錯(cuò)!

c強(qiáng)制轉(zhuǎn)換與c++強(qiáng)制轉(zhuǎn)換

c 語(yǔ)言強(qiáng)制類型轉(zhuǎn)換主要用于基礎(chǔ)的數(shù)據(jù)類型間的轉(zhuǎn)換,語(yǔ)法為:

(type-id)expression //轉(zhuǎn)換格式1 type-id(expression) //轉(zhuǎn)換格式2

c++ 除了能使用c語(yǔ)言的強(qiáng)制類型轉(zhuǎn)換外,還新增了四種強(qiáng)制類型轉(zhuǎn)換:static_cast、dynamic_cast、const_cast、reinterpret_cast,主要運(yùn)用于繼承關(guān)系類間的強(qiáng)制轉(zhuǎn)化,語(yǔ)法為:

static_cast<new_type> (expression) dynamic_cast<new_type> (expression) const_cast<new_type> (expression) reinterpret_cast<new_type> (expression)

備注:new_type為目標(biāo)數(shù)據(jù)類型,expression為原始數(shù)據(jù)類型變量或者表達(dá)式。
《Effective C++》中將c語(yǔ)言強(qiáng)制類型轉(zhuǎn)換稱為舊式轉(zhuǎn)型,c++強(qiáng)制類型轉(zhuǎn)換稱為新式轉(zhuǎn)型。

static_cast、dynamic_cast、const_cast、reinterpret_cast

static_cast

static_cast 相當(dāng)于傳統(tǒng)的C語(yǔ)言里的強(qiáng)制轉(zhuǎn)換,該運(yùn)算符把 expression 轉(zhuǎn)換為 new_type 類型,用來(lái)強(qiáng)迫隱式轉(zhuǎn)換,例如non-const對(duì)象轉(zhuǎn)為const對(duì)象,編譯時(shí)檢查,用于非多態(tài)的轉(zhuǎn)換,可以轉(zhuǎn)換指針及其他,但沒(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)換的安全性也要開發(fā)人員來(lái)保證。
  • 把空指針轉(zhuǎn)換成目標(biāo)類型的空指針。
  • 把任何類型的表達(dá)式轉(zhuǎn)換成void類型。
  • 注意:static_cast不能轉(zhuǎn)換掉expression的const、volatile、或者_(dá)_unaligned屬性。

    基本類型數(shù)據(jù)轉(zhuǎn)換舉例如下:

    char a = 'a'; int b = static_cast<char>(a);//正確,將char型數(shù)據(jù)轉(zhuǎn)換成int型數(shù)據(jù) double *c = new double; void *d = static_cast<void*>(c);//正確,將double指針轉(zhuǎn)換成void指針 int e = 10; const int f = static_cast<const int>(e);//正確,將int型數(shù)據(jù)轉(zhuǎn)換成const int型數(shù)據(jù) const int g = 20; int *h = static_cast<int*>(&g);//編譯錯(cuò)誤,static_cast不能轉(zhuǎn)換掉g的const屬性

    貌似 static_cast<char>(a); 應(yīng)該是 static_cast<int>(a);

    類上行和下行轉(zhuǎn)換:

    if(Derived *dp = static_cast<Derived *>(bp)){//下行轉(zhuǎn)換是不安全的//使用dp指向的Derived對(duì)象 } else{//使用bp指向的Base對(duì)象 }if(Base*bp = static_cast<Derived *>(dp)){//上行轉(zhuǎn)換是安全的//使用bp指向的Derived對(duì)象 } else{//使用dp指向的Base對(duì)象 }

    dynamic_cast

    dynamic_cast<type*>(e) dynamic_cast<type&>(e) dynamic_cast<type&&>(e)

    type 必須是一個(gè)類類型,在第一種形式中,type必須是一個(gè)有效的指針,在第二種形式中,type必須是一個(gè)左值,在第三種形式中,type必須是一個(gè)右值。在上面所有形式中,e的類型必須符合以下三個(gè)條件中的任何一個(gè):e的類型是是目標(biāo)類型type的公有派生類、e的類型是目標(biāo)type的共有基類或者e的類型就是目標(biāo)type的的類型。如果一條dynamic_cast語(yǔ)句的轉(zhuǎn)換目標(biāo)是指針類型并且失敗了,則結(jié)果為0。如果轉(zhuǎn)換目標(biāo)是引用類型并且失敗了,則dynamic_cast運(yùn)算符將拋出一個(gè)std::bad_cast異常(該異常定義在typeinfo標(biāo)準(zhǔn)庫(kù)頭文件中)。e也可以是一個(gè)空指針,結(jié)果是所需類型的空指針。

    dynamic_cast主要用于類層次間的上行轉(zhuǎn)換和下行轉(zhuǎn)換,還可以用于類之間的交叉轉(zhuǎn)換(cross cast)。
    在類層次間進(jìn)行上行轉(zhuǎn)換時(shí),dynamic_cast和static_cast的效果是一樣的;
    在進(jìn)行下行轉(zhuǎn)換時(shí),dynamic_cast具有類型檢查的功能,比static_cast更安全。dynamic_cast是唯一無(wú)法由舊式語(yǔ)法執(zhí)行的動(dòng)作,也是唯一可能耗費(fèi)重大運(yùn)行成本的轉(zhuǎn)型動(dòng)作。

    指針類型

    舉例,Base為包含至少一個(gè)虛函數(shù)的基類,Derived是Base的共有派生類,如果有一個(gè)指向Base的指針bp,我們可以在運(yùn)行時(shí)將它轉(zhuǎn)換成指向Derived的指針,代碼如下:

    if(Derived *dp = dynamic_cast<Derived *>(bp)){//使用dp指向的Derived對(duì)象 } else{//使用bp指向的Base對(duì)象 }

    值得注意的是,在上述代碼中,if語(yǔ)句中定義了dp,這樣做的好處是可以在一個(gè)操作中同時(shí)完成類型轉(zhuǎn)換和條件檢查兩項(xiàng)任務(wù)。

    引用類型

    因?yàn)椴淮嬖谒^空引用,所以引用類型的dynamic_cast轉(zhuǎn)換與指針類型不同,在引用轉(zhuǎn)換失敗時(shí),會(huì)拋出std::bad_cast異常,該異常定義在頭文件typeinfo中。

    void f(const Base &b){try{const Derived &d = dynamic_cast<const Base &>(b); //使用b引用的Derived對(duì)象}catch(std::bad_cast){//處理類型轉(zhuǎn)換失敗的情況} }

    const_cast

    const_cast,用于修改類型的const或volatile屬性。
    該運(yùn)算符用來(lái)修改類型的const(唯一有此能力的C+±style轉(zhuǎn)型操作符)或volatile屬性。除了const 或volatile修飾之外, new_type和expression的類型是一樣的。

  • 常量指針被轉(zhuǎn)化成非常量的指針,并且仍然指向原來(lái)的對(duì)象;
  • 常量引用被轉(zhuǎn)換成非常量的引用,并且仍然指向原來(lái)的對(duì)象;
  • const_cast一般用于修改底指針。如const char *p形式。
  • 舉例轉(zhuǎn)換如下:

    const int g = 20; int *h = const_cast<int*>(&g); // 去掉const常量const屬性 const int g = 20; int &h = const_cast<int &>(g); // 去掉const引用const屬性const char *g = "hello"; char *h = const_cast<char *>(g); // 去掉const指針const屬性

    reinterpret_cast

    new_type 必須是一個(gè)指針、引用、算術(shù)類型、函數(shù)指針或者成員指針。它可以把一個(gè)指針轉(zhuǎn)換成一個(gè)整數(shù),也可以把一個(gè)整數(shù)轉(zhuǎn)換成一個(gè)指針(先把一個(gè)指針轉(zhuǎn)換成一個(gè)整數(shù),再把該整數(shù)轉(zhuǎn)換成原類型的指針,還可以得到原先的指針值)。
    reinterpret_cast意圖執(zhí)行低級(jí)轉(zhuǎn)型,實(shí)際動(dòng)作(及結(jié)果)可能取決于編輯器,這也就表示它不可移植。
      舉一個(gè)錯(cuò)誤使用reintepret_cast例子,將整數(shù)類型轉(zhuǎn)換成函數(shù)指針后,vc++在執(zhí)行過(guò)程中會(huì)報(bào)"…中的 0xxxxxxxxx 處有未經(jīng)處理的異常: 0xC0000005: Access violation"錯(cuò)誤:

    #include <iostream> using namespace std; int output(int p){cout << p <<endl;return 0; }typedef int (*test_func)(int );//定義函數(shù)指針test_func int main(){int p = 10;test_func fun1 = output;fun1(p);//正確test_func fun2 = reinterpret_cast<test_func>(&p);fun2(p);//...處有未經(jīng)處理的異常: 0xC0000005: Access violationreturn 0; }

    IBM的C++指南、C++之父Bjarne Stroustrup的FAQ網(wǎng)頁(yè)和MSDN的Visual C++也都指出:錯(cuò)誤的使用reinterpret_cast很容易導(dǎo)致程序的不安全,只有將轉(zhuǎn)換后的類型值轉(zhuǎn)換回到其原始類型,這樣才是正確使用reinterpret_cast方式。
    MSDN中也提到了,實(shí)際中可將reinterpret_cast應(yīng)用到哈希函數(shù)中,如下(64位系統(tǒng)中需將unsigned int修改為unsigned long):

    // expre_reinterpret_cast_Operator.cpp // compile with: /EHsc #include <iostream>// Returns a hash code based on an address unsigned short Hash( void *p ) {unsigned int val = reinterpret_cast<unsigned int>( p );return ( unsigned short )( val ^ (val >> 16)); }using namespace std; int main() {int a[20];for ( int i = 0; i < 20; i++ )cout << Hash( a + i ) << endl; }

    另外,static_cast和reinterpret_cast的區(qū)別主要在于多重繼承,比如

    class A {public:int m_a; };class B {public:int m_b; };class C : public A, public B {};

    那么對(duì)于以下代碼:

    C c; printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));

    前兩個(gè)的輸出值是相同的,最后一個(gè)則會(huì)在原基礎(chǔ)上偏移4個(gè)字節(jié),這是因?yàn)閟tatic_cast計(jì)算了父子類指針轉(zhuǎn)換的偏移量,并將之轉(zhuǎn)換到正確的地址(c里面有m_a,m_b,轉(zhuǎn)換為B*指針后指到m_b處),而reinterpret_cast卻不會(huì)做這一層轉(zhuǎn)換。
    因此, 你需要謹(jǐn)慎使用 reinterpret_cast。

    c++強(qiáng)制轉(zhuǎn)換注意事項(xiàng)

    新式轉(zhuǎn)換較舊式轉(zhuǎn)換更受歡迎。原因有二,一是新式轉(zhuǎn)型較易辨別,能簡(jiǎn)化“找出類型系統(tǒng)在哪個(gè)地方被破壞”的過(guò)程;二是各轉(zhuǎn)型動(dòng)作的目標(biāo)愈窄化,編譯器愈能診斷出錯(cuò)誤的運(yùn)用。
    盡量少使用轉(zhuǎn)型操作,尤其是dynamic_cast,耗時(shí)較高,會(huì)導(dǎo)致性能的下降,盡量使用其他方法替代。

    參考資料:

    a):http://en.cppreference.com/w/cpp/language/static_cast
    b):http://en.cppreference.com/w/cpp/language/dynamic_cast
    c):http://en.cppreference.com/w/cpp/language/const_cast
    d):http://en.cppreference.com/w/cpp/language/reinterpret_cast
    e):《Effective C++》條款27:盡量少做轉(zhuǎn)型動(dòng)作
    f): 百度百科
    g) 《C++ Primer》

    總結(jié)

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

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