青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Jiang's C++ Space

創作,也是一種學習的過程。

   :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::

三年前有場筆試,(注:三年前我在blog.csdn.net上發表過一篇同樣標題的文章,本想直接轉過來,但發現其中很多不妥之處,因此重寫)其中碰到一道題目,讓我列舉C++中的四種cast的轉換分別是什么,有何作用,并舉例說明,我雖然早知道C++有四種cast轉換,但平常使用非常少也就沒注意,所以那題我是沒做出來,回來后打算對C++的這些類型轉換方法進行小結,我做了許多實驗,于是有此文,希望對你有些幫助。

下文中的“常規類型”指的是int、double、float、bool……這些非結構化類型,也就是不包括struct和class類型。“舊式轉換”指的是C語言風格的“(NewType)(Val)”方式的轉換。

1、指針=>常規類型

比如我們需要打印一個指針的值(它指向的地址)的時候,我們指針直接轉換為整數,用printf輸出個16進制的地址。我們可以用舊式轉換,或者reinterpret_cast,其它轉換都是不可以的。

    CIndepend oIndepend;
    CIndepend 
* pIndepend = &oIndepend;
    unsigned 
char cTest= (unsigned char )pIndepend;
    unsigned 
short sTest = (unsigned short )pIndepend;
    unsigned 
int iTest = (unsigned int )pIndepend;

在32位系統中,指針其實是個32位的無符號整型,要正常輸出指針的值,正確做法是把它轉換為一個無符號32位整形數輸出(有符號的可能導致輸出不正確),如果轉換為一個16位的,或者8位的,那將丟失數據,當然了,前面這段代碼不會出現任何error和warning,你知道你在干什么即可。剛說了,我們除了舊式轉換還可以用reinterpret_cast,于是上面的代碼可以這樣寫:

    unsigned char cTest= reinterpret_cast<unsigned char >(pIndepend);
    unsigned 
short sTest = reinterpret_cast<unsigned short>(pIndepend);
    unsigned 
int iTest = reinterpret_cast<unsigned int>(pIndepend);

也是沒有任何問題的,運行效果一樣,那我們能不能把指針轉換為浮點型呢?這樣:

    float fTest = reinterpret_cast<float>(pIndepend);
    
double dTest = reinterpret_cast<double>(pIndepend);

不行,你試試看就知道了,你會得到這樣的編譯錯誤:

error C2440: 'reinterpret_cast' : cannot convert from 'class CIndepend *' to 'float'
        There is no context in which this conversion is possible
error C2440: 'reinterpret_cast' : cannot convert from 'class CIndepend *' to 'double'
        There is no context in which this conversion is possible

其實將指針轉換為浮點數這種做法就很怪異嘛,你不覺得嗎?這樣有什么用???不過你一定要這樣干的話也不是沒有辦法,看代碼:

    float fTest = reinterpret_cast<float &>(pIndepend);
    
double dTest = reinterpret_cast<double &>(pIndepend);

加個小小的“&”符號就可以了,C++會不顧一切地把pIndepend這個變量當作一個float和double,把指針的值“理解”為float和double,當然,這樣獲得的浮點數的值是沒什么實際意義的,因為指針的值是32位無符號整型,而浮點數有它自己特定的格式,這么一轉換就牛頭不對馬嘴。你還可以這樣寫:

      float fTest = (float &)pIndepend;
      
double dTest = (double &)pIndepend;

效果一樣,得到的也是無意義的值。

2、常規類型=>指針

就是反過來羅,可能不說大家都能猜到結果了。把常規類型轉換為指針有什么用呢?可能有點用,比如我們在某些特殊的場合要求一個指針指向一個特別的地址,這時候我們可以直接給指針賦個值,當然了,這個值應該是整型:

    CIndepend * pIndepend;

    
char cVal = 1;
    
short sVal = 2;
    
int iVal = 3;

    pIndepend 
= (CIndepend *)cVal;
    pIndepend 
= (CIndepend *)sVal;
    pIndepend 
= (CIndepend *)iVal;

這樣是沒問題的,那浮點數呢?——又來了,浮點數轉換為指針?這怎么算啊?顯然這是不行的,如果真的需要“轉換”,那就先把浮點數轉換為整型,然后再賦值給指針吧。這個時候,dynamic_cast和static_cast都是不行的。

3、基本類型轉換

比如int轉換為float,char轉變為short,很多時候我們都“默認”了這種轉換,即使沒有顯式指定用舊式轉換還是static_cast。在這種類型的轉換中,舊式轉換和static_cast的表現非常地類似:

    double dVal = 5.0;

    
char cVal = static_cast<char>(dVal);
    
short sVal = static_cast<short>(dVal);
    
int iVal = static_cast<int>(dVal);

    cVal 
= (char)(dVal);
    sVal 
= (short)(dVal);
    iVal 
= (int)(dVal);

而dynamic_cast還是不可行,那……reinterpret_cast呢?不妨試試看:

    double dVal = 5.0;

    
char cVal = reinterpret_cast<char>(dVal);
    
short sVal = reinterpret_cast<short>(dVal);
    
int iVal = reinterpret_cast<int>(dVal);

一編譯,就出下面的錯誤:

error C2440: 'reinterpret_cast' : cannot convert from 'double' to 'char'
        Conversion is a valid standard conversion, which can be performed implicitly or by use of static_cast, C-style cast or function-style cast
error C2440: 'reinterpret_cast' : cannot convert from 'double' to 'short'
        Conversion is a valid standard conversion, which can be performed implicitly or by use of static_cast, C-style cast or function-style cast
error C2440: 'reinterpret_cast' : cannot convert from 'double' to 'int'
        Conversion is a valid standard conversion, which can be performed implicitly or by use of static_cast, C-style cast or function-style cast

說這是個有效標準轉換,請使用static_cast或者C風格的舊式轉換。reinterpret_cast不是號稱最寬松的轉換么?怎么不行了?你一定要它行也是沒問題的,和前面的那樣,加個“&”符號:

    char cVal = reinterpret_cast<char &>(dVal);
    
short sVal = reinterpret_cast<short &>(dVal);
    
int iVal = reinterpret_cast<int &>(dVal);

但結果并不是你想要的結果,因為這樣reinterpret_cast會不管三七二十一,直接把dVal的東西當作是一個char,short和int,很明顯,double是有一定的格式的,將double直接“理解”為char,short或者int一定會有問題。

4、class的轉換

上一節說的是基本類型,那對于類呢?一個類直接轉換為另一個類,這看起來確實有些荒謬,不過強大而靈活的C++卻偏偏允許了這種行為。看代碼:

class CBase
{
public:
    CBase(){};
    
int m_iBase;
};

class CIndepend
{
public:
    CIndepend(){};
    
int m_iIndepend;
};

int main(int argc, char* argv[])
{
    CBase oBase;
    CIndepend oIndepend 
= reinterpret_cast<CIndepend &>(oBase);
    
return 0;
}

居然編譯過去了,運行貌似也沒什么問題,當然轉換過程和前面的差不多,就是把oBase理解為一個CIndepend對象,這個賦值運算執行“位拷貝”,這種方式的轉換在實際中是碰不到的,起碼我想不出有什么理由使用它。這種情況下,其它的轉換方式都是不可行的。

5、class=>指針 or 指針=>class

這種行為更怪異,class直接理解為指針?這其實是不可行的,跟前面提到的浮點數轉換為指針一樣,如果實在需要,就把class轉變為整型,然后整型轉換為指針:

CIndepend * pIndepend = reinterpret_cast<CIndepend *>(reinterpret_cast<unsigned int &>(oBase));

可這……這啥意思呢?哈哈,別問我。反過來,指針轉換為class恐怕也令人費解:

    CDerived oDerived;
    CDerived 
*pDerived = &oDerived;
    CIndepend oIndepend 
= reinterpret_cast<CIndepend &>(pDerived);

能擔當起這種怪異的工作的,唯reinterpret_cast是也,這樣會產生什么后果呢?指針是個32位無符號整型,將它強制理解為一個CIndepend,然后作位拷貝,理所當然,oIndepend的值會被改變,而且還有訪問越界的風險,導致內容混亂甚至程序崩潰。

6、指針之間的轉換

前面一直沒提起的一種轉換就是dynamic_cast,因為它是最為嚴格的一種轉換,它只能完成指針到指針的轉換,而且還有限制??催@個:

    CDerived oDerived;
    CDerived 
*pDerived = &oDerived;
    
CIndepend *pIndepend = dynamic_cast<CIndepend *>(pDerived);

編譯出錯了:

error C2683: dynamic_cast : 'CDerived' is not a polymorphic type
        D:\work\CastTest\CastTest.cpp(13) : see declaration of 'CDerived'

因為CDerived和CIndepend沒有繼承關系,把dynamic_cast換成static_cast還是不行的,會出另外一個錯:

error C2440: 'static_cast' : cannot convert from 'class CDerived *' to 'class CIndepend *'
        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

編譯器說這是沒有關系的兩個指針,應該用reinterpret_cast或者C風格的舊式轉換,再看:

    //CDerived是CBase的子類
    CBase oBase;
    CBase 
*pBase = &oBase;
    CDerived 
*pDerived = dynamic_cast<CDerived *>(pBase);

基類指針轉換為子類指針,行不行呢?出錯,錯誤跟剛才的一樣,記住,dynamic_cast僅僅可以把子類指針轉換為基類指針,別的都不行!上面這段代碼如果不用dynamic_cast,而是用static_cast,就能編譯通過,static_cast的要求來得比較寬松。

OK,到這里為止,大家都知道什么時候用什么轉換是可以的了,問題是C++為什么搞出怎么多轉換出來呢?我想很大程度上是兼顧了安全性和靈活性,要想安全,class指針的轉換就使用dynamic_cast;一般情況下我們認為,static_cast也是安全的;C風格的舊式轉換則靈活一些,它允許任意類型指針之間的轉換;而reinterpret_cast就更加了,什么亂七八糟都可以。那從功能強弱上排個序,我想從強到弱應該是:reinterpret_cast,舊式轉換,static_cast,dynamic_cast。

Oh,還有一種轉換,差點忘了,就是const_cast,不過這種轉換比較特別,可以獨立開來,它的功能就是去除一個變量的const屬性,也就是說,允許修改常量的值,哈哈,修改常量的值?既然要修改常量的值,那為什么還要聲明它為常量?——這也是C++靈活的一個體現。不過const_cast其實有個問題,有時候它并不能真正改變一個常量的值,關于這個,在我的另一篇博文中有講述,此文還在csdn.net,晚些時候移過來,我再給個鏈接。

posted on 2009-04-23 18:02 Jiang Guogang 閱讀(1792) 評論(0)  編輯 收藏 引用 所屬分類: Knowledge
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            aa成人免费视频| 久久久亚洲综合| 一本色道久久综合亚洲精品小说| 亚洲欧洲一区二区三区在线观看| 国产欧美va欧美不卡在线| 国产一区二区三区黄视频| 精品999网站| 亚洲一区二区成人| 久久夜色精品国产噜噜av| 亚洲高清av| 欧美亚洲一区三区| 欧美日韩亚洲视频| 一区二区亚洲| 亚洲精品久久久久久久久久久| 欧美亚洲专区| 亚洲破处大片| 免费成人高清视频| 久久裸体艺术| 国内外成人免费激情在线视频| 亚洲免费成人| 麻豆精品传媒视频| 欧美在线免费视屏| 国产欧美日韩高清| 亚洲国产裸拍裸体视频在线观看乱了 | 欧美午夜不卡| 在线观看三级视频欧美| 久久国产精品久久久久久电车| 久久国产一区| 欧美成人一区二区三区在线观看| 国内精品视频在线播放| 亚洲精一区二区三区| 欧美视频一区| 午夜精品久久久99热福利| 亚洲欧洲偷拍精品| 国产在线精品一区二区夜色| 91久久精品国产91久久性色| 国产一区二区三区精品欧美日韩一区二区三区 | 久久综合99re88久久爱| 国内精品美女在线观看| av不卡在线看| 亚洲伦理在线观看| 久久人人爽人人爽| 亚洲欧洲日韩女同| 久久久国产一区二区三区| 精品av久久707| 亚洲欧美日韩一区二区三区在线| 国产精品亚洲一区二区三区在线| 亚洲尤物精选| 欧美一区2区三区4区公司二百| 99在线视频精品| 99pao成人国产永久免费视频| 国产精品福利网| 久久精品一本| 欧美国产高清| 午夜一区二区三区不卡视频| 久久激情久久| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 欧美一级理论性理论a| 亚洲伊人一本大道中文字幕| 欧美日韩国产限制| 久久国产精品72免费观看| 国产精品国产一区二区| 中文亚洲免费| 在线观看91久久久久久| 久久精品色图| 免费在线视频一区| 久久综合成人精品亚洲另类欧美| 欧美成人精品在线| 欧美岛国激情| 欧美日韩国产在线观看| 亚洲欧洲日产国产综合网| 99亚洲伊人久久精品影院红桃| 欧美成人乱码一区二区三区| 亚洲娇小video精品| 一区二区日本视频| 美腿丝袜亚洲色图| 午夜日韩av| 韩国在线视频一区| 亚洲性感激情| 亚洲精品国产精品国自产在线 | 欧美日韩精品综合在线| 一本一本a久久| 久久成人18免费网站| 狠狠色伊人亚洲综合成人| 免费久久99精品国产自在现线| 欧美亚洲一级片| 一区二区在线观看视频在线观看| 美女久久一区| 亚洲在线日韩| 亚洲婷婷在线| 欧美精品亚洲精品| 欧美凹凸一区二区三区视频| 日韩写真在线| 免费日韩视频| 亚洲影音一区| 牛夜精品久久久久久久99黑人| 9l国产精品久久久久麻豆| 国产精品一区二区久久久| 一区二区三区欧美成人| 久久嫩草精品久久久精品一| 亚洲美女性视频| 国产亚洲人成a一在线v站 | 久久精品综合一区| 日韩一级不卡| 欧美激情免费在线| 精品成人一区二区三区| 欧美日韩成人| 久久久夜精品| 欧美一区二区播放| 亚洲美女av黄| 欧美成人亚洲成人| 久久av免费一区| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 亚洲一区二区成人| 亚洲欧洲三级电影| 国产综合色产在线精品| 国产精品久久九九| 欧美高清hd18日本| 久久视频在线看| 午夜在线观看欧美| 久久久人人人| 欧美在线一级视频| 亚洲一区一卡| 亚洲视频日本| 一区二区日韩伦理片| 亚洲日韩第九十九页| 亚洲电影专区| 欧美日韩国产精品| 欧美激情视频一区二区三区在线播放| 欧美综合国产| 亚洲精品乱码久久久久久黑人 | 欧美大色视频| 老牛国产精品一区的观看方式| 欧美一区二区三区成人| 亚洲一区二区三区四区五区黄| 亚洲精品一区二区三区99| 亚洲国内精品| 亚洲国产精品黑人久久久| 欧美大片免费| 亚洲国产精品久久久久秋霞影院 | 欧美一级播放| 久久www成人_看片免费不卡| 午夜精品久久久久久久久久久| 亚洲一区999| 香蕉国产精品偷在线观看不卡| 亚洲自拍偷拍网址| 欧美在线你懂的| 久久亚洲不卡| 亚洲国产欧美在线人成| 亚洲精品系列| 亚洲性夜色噜噜噜7777| 香港成人在线视频| 久久精品系列| 欧美国产一区二区在线观看| 欧美日韩成人综合在线一区二区 | 国产精品一区亚洲| 国产亚洲一区二区三区| 在线播放视频一区| 99re这里只有精品6| 亚洲小视频在线观看| 久久精品成人欧美大片古装| 久热这里只精品99re8久| 亚洲福利视频在线| 中文精品99久久国产香蕉| 午夜精品久久久久久久99水蜜桃 | 亚洲精品1234| 国产亚洲精品久久久久动| 狠狠色丁香婷综合久久| 亚洲久久一区| 欧美亚洲免费高清在线观看| 欧美高清在线视频| 一区二区三区视频在线播放| 欧美在线亚洲| 欧美日韩成人精品| 精品69视频一区二区三区 | 国产日韩精品久久久| 亚洲电影免费观看高清完整版在线 | 亚洲欧美日韩国产另类专区| 久久久久久久久伊人| 欧美日韩色综合| 伊甸园精品99久久久久久| 亚洲午夜激情网页| 欧美成人免费全部| 亚洲欧美日韩区| 欧美日韩激情小视频| 在线不卡a资源高清| 午夜日韩av| 亚洲人成网站999久久久综合| 欧美一区二区在线观看| 欧美日韩精品一区二区三区四区| 精品999成人| 欧美亚洲一区三区| 夜夜精品视频一区二区| 久久综合网络一区二区| 国产日韩一区二区| 国产一区二区三区成人欧美日韩在线观看 | 亚洲精品美女久久7777777| 一区二区三区精品国产| 久久人人爽人人| 国产一区二区三区四区|