欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++強(qiáng)制類(lèi)型轉(zhuǎn)換(static_cast、dynamic_cast、const_cast、reinterpret_cast)

 更新時(shí)間:2021年08月04日 11:21:21   作者:SpartacusIn21  
本文主要介紹了C++強(qiáng)制類(lèi)型轉(zhuǎn)換,主要介紹了static_cast、dynamic_cast、const_cast、reinterpret_cast的4種方法,感興趣的可以了解一下

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

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

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

c++除了能使用c語(yǔ)言的強(qiáng)制類(lèi)型轉(zhuǎn)換外,還新增了四種強(qiáng)制類(lèi)型轉(zhuǎn)換:static_cast、dynamic_cast、const_cast、reinterpret_cast,主要運(yùn)用于繼承關(guān)系類(lèi)間的強(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ù)類(lèi)型,expression為原始數(shù)據(jù)類(lèi)型變量或者表達(dá)式。

《Effective C++》中將c語(yǔ)言強(qiáng)制類(lèi)型轉(zhuǎn)換稱(chēng)為舊式轉(zhuǎn)型,c++強(qiáng)制類(lèi)型轉(zhuǎn)換稱(chēng)為新式轉(zhuǎn)型。

2. 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)型,用來(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)型檢查來(lái)保證轉(zhuǎn)換的安全性。它主要有如下幾種用法:
①用于類(lèi)層次結(jié)構(gòu)中基類(lèi)(父類(lèi))和派生類(lèi)(子類(lèi))之間指針或引用的轉(zhuǎn)換。
進(jìn)行上行轉(zhuǎn)換(把派生類(lèi)的指針或引用轉(zhuǎn)換成基類(lèi)表示)是安全的;
進(jìn)行下行轉(zhuǎn)換(把基類(lèi)指針或引用轉(zhuǎn)換成派生類(lèi)表示)時(shí),由于沒(méi)有動(dòng)態(tài)類(lèi)型檢查,所以是不安全的。
②用于基本數(shù)據(jù)類(lèi)型之間的轉(zhuǎn)換,如把int轉(zhuǎn)換成char,把int轉(zhuǎn)換成enum。這種轉(zhuǎn)換的安全性也要開(kāi)發(fā)人員來(lái)保證。
③把空指針轉(zhuǎn)換成目標(biāo)類(lèi)型的空指針。
④把任何類(lèi)型的表達(dá)式轉(zhuǎn)換成void類(lèi)型。
注意:static_cast不能轉(zhuǎn)換掉expression的const、volatile、或者_(dá)_unaligned屬性。

基本類(lèi)型數(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屬性

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

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

(1)指針類(lèi)型
舉例,Base為包含至少一個(gè)虛函數(shù)的基類(lèi),Derived是Base的共有派生類(lèi),如果有一個(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í)完成類(lèi)型轉(zhuǎn)換和條件檢查兩項(xiàng)任務(wù)。

(2)引用類(lèi)型

因?yàn)椴淮嬖谒^空引用,所以引用類(lèi)型的dynamic_cast轉(zhuǎn)換與指針類(lèi)型不同,在引用轉(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){
   //處理類(lèi)型轉(zhuǎn)換失敗的情況
 }
}

const_cast

const_cast,用于修改類(lèi)型的const或volatile屬性。

該運(yùn)算符用來(lái)修改類(lèi)型的const(唯一有此能力的C++-style轉(zhuǎn)型操作符)或volatile屬性。除了const 或volatile修飾之外, new_type和expression的類(lèi)型是一樣的。
①常量指針被轉(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ù)類(lèi)型、函數(shù)指針或者成員指針。它可以把一個(gè)指針轉(zhuǎn)換成一個(gè)整數(shù),也可以把一個(gè)整數(shù)轉(zhuǎn)換成一個(gè)指針(先把一個(gè)指針轉(zhuǎn)換成一個(gè)整數(shù),再把該整數(shù)轉(zhuǎn)換成原類(lèi)型的指針,還可以得到原先的指針值)。

reinterpret_cast意圖執(zhí)行低級(jí)轉(zhuǎn)型,實(shí)際動(dòng)作(及結(jié)果)可能取決于編輯器,這也就表示它不可移植。

  舉一個(gè)錯(cuò)誤使用reintepret_cast例子,將整數(shù)類(lèi)型轉(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 violation
    return 0;
}

IBM的C++指南、C++之父Bjarne Stroustrup的FAQ網(wǎng)頁(yè)和MSDN的Visual C++也都指出:錯(cuò)誤的使用reinterpret_cast很容易導(dǎo)致程序的不安全,只有將轉(zhuǎn)換后的類(lèi)型值轉(zhuǎn)換回到其原始類(lèi)型,這樣才是正確使用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ì)算了父子類(lèi)指針轉(zhuǎn)換的偏移量,并將之轉(zhuǎn)換到正確的地址(c里面有m_a,m_b,轉(zhuǎn)換為B*指針后指到m_b處),而reinterpret_cast卻不會(huì)做這一層轉(zhuǎn)換。

因此, 你需要謹(jǐn)慎使用 reinterpret_cast。

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

新式轉(zhuǎn)換較舊式轉(zhuǎn)換更受歡迎。原因有二,一是新式轉(zhuǎn)型較易辨別,能簡(jiǎn)化“找出類(lèi)型系統(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》

到此這篇關(guān)于C++強(qiáng)制類(lèi)型轉(zhuǎn)換(static_cast、dynamic_cast、const_cast、reinterpret_cast)的文章就介紹到這了,更多相關(guān)C++強(qiáng)制類(lèi)型轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++簡(jiǎn)單又輕松建立鏈?zhǔn)蕉鏄?shù)流程

    C++簡(jiǎn)單又輕松建立鏈?zhǔn)蕉鏄?shù)流程

    二叉樹(shù)的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是指,用鏈表來(lái)表示一棵二叉樹(shù),即用鏈來(lái)指示元素的邏輯關(guān)系。通常的方法是鏈表中每個(gè)結(jié)點(diǎn)由三個(gè)域組成,數(shù)據(jù)域和左右指針域,左右指針?lè)謩e用來(lái)給出該結(jié)點(diǎn)左孩子和右孩子所在的鏈結(jié)點(diǎn)的存儲(chǔ)地址
    2022-06-06
  • 通俗易懂的C++前綴和與差分算法圖文示例詳解

    通俗易懂的C++前綴和與差分算法圖文示例詳解

    這篇文章主要為大家非常通俗易懂的講解了C++前綴和與差分算法的圖文分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2021-11-11
  • Qt實(shí)現(xiàn)生成指定范圍內(nèi)隨機(jī)數(shù)與隨機(jī)字符串

    Qt實(shí)現(xiàn)生成指定范圍內(nèi)隨機(jī)數(shù)與隨機(jī)字符串

    這篇文章主要為大家詳細(xì)介紹了如何利用Qt實(shí)現(xiàn)生成指定范圍內(nèi)隨機(jī)數(shù)與隨機(jī)字符串,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以自己動(dòng)手嘗試一下
    2023-07-07
  • C語(yǔ)言中輸出空格的五種方法

    C語(yǔ)言中輸出空格的五種方法

    在C語(yǔ)言中,輸出空格可以通過(guò)使用?printf?函數(shù)來(lái)實(shí)現(xiàn),可以直接在字符串中包含空格,或者使用轉(zhuǎn)義字符來(lái)控制格式,本文給大家介紹了幾種常見(jiàn)的輸出空格的方法,需要的朋友可以參考下
    2024-08-08
  • C++另辟蹊徑計(jì)算1到n的和

    C++另辟蹊徑計(jì)算1到n的和

    從1加到100,高斯的故事,我們學(xué)過(guò)。今天,我們寫(xiě)一個(gè)程序來(lái)試試。首先,用笨方法。一個(gè)數(shù)一個(gè)數(shù)的加,我們一般人就是這樣干的嗎。在計(jì)算機(jī)程序里面,怎么辦呢?1我們把求和的功能寫(xiě)成一個(gè)可以針對(duì)不同的N運(yùn)用的,C++里面叫函數(shù)
    2023-02-02
  • 關(guān)于函數(shù)調(diào)用方式__stdcall和__cdecl詳解

    關(guān)于函數(shù)調(diào)用方式__stdcall和__cdecl詳解

    下面小編就為大家?guī)?lái)一篇關(guān)于函數(shù)調(diào)用方式__stdcall和__cdecl詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-09-09
  • Mingw64編譯wxWidgets 3.0.2常見(jiàn)錯(cuò)誤分析

    Mingw64編譯wxWidgets 3.0.2常見(jiàn)錯(cuò)誤分析

    這篇文章主要介紹了Mingw64編譯wxWidgets 3.0.2常見(jiàn)錯(cuò)誤分析,需要的朋友可以參考下
    2016-11-11
  • C++中delete和delete[]的區(qū)別

    C++中delete和delete[]的區(qū)別

    這篇文章主要介紹了C++中delete和delete[]的區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2016-03-03
  • C語(yǔ)言實(shí)現(xiàn)輸出平均成績(jī)最高學(xué)生的信息

    C語(yǔ)言實(shí)現(xiàn)輸出平均成績(jī)最高學(xué)生的信息

    這篇文章主要介紹利用C語(yǔ)言實(shí)現(xiàn)輸出平均成績(jī)最高學(xué)生的信息,文章舉例說(shuō)明并附有詳細(xì)代碼,需要的朋友可以參考一下
    2021-10-10
  • C++ vector容器縮小capacity問(wèn)題

    C++ vector容器縮小capacity問(wèn)題

    這篇文章主要介紹了C++ vector容器縮小capacity問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評(píng)論