• <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>

            的筆記

            隨時(shí)隨地編輯

            Dynamic、Static、Reinterpret、Const Cast

            一、向上類型轉(zhuǎn)換


            情形一:
            C++ code
            class A
            {
            public:
             virtual void fun()
             {
              int a=0;
             }
            };

            class B :public A
             2{
             3public:
             4    void fun()
             5    {
             6        int b=0;
             7    }

             8}
            ;
             9
            10int _tmain(int argc, _TCHAR* argv[])
            11{
            12
            13    B obj;
            14
            15    {
            16        A* p = (&obj);
            17        p->fun();
            18    }

            19
            20    {
            21        A* p = static_cast< A* >(&obj);
            22        p->fun();
            23    }

            24
            25    {
            26        A* p = dynamic_cast< A* >(&obj);
            27        p->fun();
            28    }

            29
            30    {
            31        A* p = reinterpret_cast< A* >(&obj);
            32        p->fun();
            33    }

            34
            35    return 0;
            36}

            Disassembly
             1    B obj;
             2  lea         ecx,[obj] 
             3  call        B::B (11A1104h) 
             4
             5    {
             6        A* p = (&obj);
             7  lea         eax,[obj] 
             8  mov         dword ptr [p],eax 
             9        p->fun();
            10  mov         eax,dword ptr [p] 
            11  mov         edx,dword ptr [eax] 
            12  mov         esi,esp 
            13  mov         ecx,dword ptr [p] 
            14  mov         eax,dword ptr [edx] 
            15  call        eax  
            16  cmp         esi,esp 
            17  call        @ILT+365(__RTC_CheckEsp) (11A1172h) 
            18    }

            19
            20    {
            21        A* p = static_cast< A* >(&obj);
            22  lea         eax,[obj] 
            23  mov         dword ptr [p],eax 
            24        p->fun();
            25  mov         eax,dword ptr [p] 
            26  mov         edx,dword ptr [eax] 
            27  mov         esi,esp 
            28  mov         ecx,dword ptr [p] 
            29  mov         eax,dword ptr [edx] 
            30  call        eax  
            31  cmp         esi,esp 
            32  call        @ILT+365(__RTC_CheckEsp) (11A1172h) 
            33    }

            34
            35    {
            36        A* p = dynamic_cast< A* >(&obj);
            37  lea         eax,[obj] 
            38  mov         dword ptr [p],eax 
            39        p->fun();
            40  mov         eax,dword ptr [p] 
            41  mov         edx,dword ptr [eax] 
            42  mov         esi,esp 
            43  mov         ecx,dword ptr [p] 
            44  mov         eax,dword ptr [edx] 
            45  call        eax  
            46  cmp         esi,esp 
            47  call        @ILT+365(__RTC_CheckEsp) (11A1172h) 
            48    }

            49
            50    {
            51        A* p = reinterpret_cast< A* >(&obj);
            52  lea         eax,[obj] 
            53  mov         dword ptr [p],eax 
            54        p->fun();
            55  mov         eax,dword ptr [p] 
            56  mov         edx,dword ptr [eax] 
            57  mov         esi,esp 
            58  mov         ecx,dword ptr [p] 
            59  mov         eax,dword ptr [edx] 
            60  call        eax  
            61  cmp         esi,esp 
            62  call        @ILT+365(__RTC_CheckEsp) (11A1172h) 
            63    }

            看看B:B()的代碼,這個(gè)編譯器自動(dòng)幫我們加上去的代碼,如果沒(méi)有虛報(bào)是不會(huì)有的。
             1B::B:
             2  push        ebp  
             3  mov         ebp,esp 
             4  sub         esp,0CCh 
             5  push        ebx  
             6  push        esi  
             7  push        edi  
             8  push        ecx  
             9  lea         edi,[ebp-0CCh] 
            10  mov         ecx,33h 
            11  mov         eax,0CCCCCCCCh 
            12  rep stos    dword ptr es:[edi] 
            13  pop         ecx  
            14  mov         dword ptr [ebp-8],ecx 
            15  mov         ecx,dword ptr [this
            16  call        A::A (1321109h) 
            17  mov         eax,dword ptr [this
            18  mov         dword ptr [eax],offset B::`vftable' (1325740h) 
            19  mov         eax,dword ptr [this
            20  pop         edi  
            21  pop         esi  
            22  pop         ebx  
            23  add         esp,0CCh 
            24  cmp         ebp,esp 
            25  call        @ILT+365(__RTC_CheckEsp) (1321172h) 
            26  mov         esp,ebp 
            27  pop         ebp  
            28  ret              


            情形二:

            C++ CODE
            只是在上文改動(dòng)一處:去掉A::fun()的聲明virtual。

            Disassembly對(duì)比
                              左:無(wú)virtual聲明                                                           右:有virtual聲明

            結(jié)論: 無(wú)論哪種cast,向上類型都一樣。函數(shù)調(diào)用只與虛表有關(guān)。向上類型轉(zhuǎn)換是最常見(jiàn)的一種轉(zhuǎn)換,常見(jiàn)的大部分代碼都是用"向上類型轉(zhuǎn)換+虛函數(shù)"這種黃金組合完成一些c++類庫(kù),例如MFC,QT,OGRE.這種轉(zhuǎn)換很符合常規(guī),基本不會(huì)出錯(cuò)。

            二、向下類型轉(zhuǎn)換

            情形一:

            C++ CODE

            A和B的聲明同上,只是改變A::fun()是虛函數(shù)。
             1    A obj;
             2
             3    {
             4        //B* p = (&obj);
             5        //p->fun();
             6        //error C2440: 'initializing' : cannot convert from 'A *' to 'B *'
             7        //Cast from base to derived requires dynamic_cast or static_cast
             8    }

             9
            10    {
            11        B* p = static_cast< B* >(&obj);
            12        p->fun();
            13    }

            14
            15    {
            16        B* p = dynamic_cast< B* >(&obj);
            17        p->fun();
            18    }

            19
            20    {
            21        B* p = reinterpret_cast< B* >(&obj);
            22        p->fun();
            23    }

            Disassembly
             1    A obj;
             2  lea         ecx,[obj] 
             3  call        A::A (9310FFh) 
             4
             5    {
             6        //B* p = (&obj);
             7        //p->fun();
             8        //error C2440: 'initializing' : cannot convert from 'A *' to 'B *'
             9        //Cast from base to derived requires dynamic_cast or static_cast
            10    }

            11
            12    {
            13        B* p = static_cast< B* >(&obj);
            14  lea         eax,[obj] 
            15  mov         dword ptr [p],eax 
            16        p->fun();
            17  mov         eax,dword ptr [p] 
            18  mov         edx,dword ptr [eax] 
            19  mov         esi,esp 
            20  mov         ecx,dword ptr [p] 
            21  mov         eax,dword ptr [edx] 
            22  call        eax  
            23  cmp         esi,esp 
            24  call        @ILT+355(__RTC_CheckEsp) (931168h) 
            25    }

            26
            27    {
            28        B* p = dynamic_cast< B* >(&obj);
            29  push        0    
            30  push        offset B `RTTI Type Descriptor' (937014h) 
            31  push        offset A `RTTI Type Descriptor' (937000h) 
            32  push        0    
            33  lea         eax,[obj] 
            34  push        eax  
            35  call        @ILT+450(___RTDynamicCast) (9311C7h) 
            36  add         esp,14h 
            37  mov         dword ptr [p],eax 
            38        p->fun();
            39  mov         eax,dword ptr [p] 
            40  mov         edx,dword ptr [eax] 
            41  mov         esi,esp 
            42  mov         ecx,dword ptr [p] 
            43  mov         eax,dword ptr [edx] 
            44  call        eax  
            45  cmp         esi,esp 
            46  call        @ILT+355(__RTC_CheckEsp) (931168h) 
            47    }

            48
            49    {
            50        B* p = reinterpret_cast< B* >(&obj);
            51  lea         eax,[obj] 
            52  mov         dword ptr [p],eax 
            53        p->fun();
            54  mov         eax,dword ptr [p] 
            55  mov         edx,dword ptr [eax] 
            56  mov         esi,esp 
            57  mov         ecx,dword ptr [p] 
            58  mov         eax,dword ptr [edx] 
            59  call        eax  
            60  cmp         esi,esp 
            61  call        @ILT+355(__RTC_CheckEsp) (931168h) 
            62    }

            情形二:
            C++ CODE
            A和B的聲明同上,只是改變A::fun()不是虛函數(shù)。
                A obj;

                
            {
                    
            //B* p = (&obj);
                    
            //p->fun();
                    
            //error C2440: 'initializing' : cannot convert from 'A *' to 'B *'
                    
            //Cast from base to derived requires dynamic_cast or static_cast
                }


                
            {
                    B
            * p = static_cast< B* >(&obj);
                    p
            ->fun();
                }


                
            {
                    
            //B* p = dynamic_cast< B* >(&obj);
                    
            //p->fun();
                    
            //error C2683: 'dynamic_cast' : 'A' is not a polymorphic type
                    
            //*    1>        */e:\develop\test\testr555\testr555.cpp(7) : see declaration of 'A'
                }


                
            {
                    B
            * p = reinterpret_cast< B* >(&obj);
                    p
            ->fun();
                }


            Disassembly
                A obj;

                
            {
                    
            //B* p = (&obj);
                    
            //p->fun();
                    
            //error C2440: 'initializing' : cannot convert from 'A *' to 'B *'
                    
            //Cast from base to derived requires dynamic_cast or static_cast
                }


                
            {
                    B
            * p = static_cast< B* >(&obj);
              lea         eax,[obj] 
              mov         dword ptr [p],eax 
                    p
            ->fun();
              mov         ecx,dword ptr [p] 
              call        B::fun (10C1028h) 
                }


                
            {
                    
            //B* p = dynamic_cast< B* >(&obj);
                    
            //p->fun();
                    
            //error C2683: 'dynamic_cast' : 'A' is not a polymorphic type
                    
            //*    1>        */e:\develop\test\testr555\testr555.cpp(7) : see declaration of 'A'
                }


                
            {
                    B
            * p = reinterpret_cast< B* >(&obj);
              lea         eax,[obj] 
              mov         dword ptr [p],eax 
                    p
            ->fun();
              mov         ecx,dword ptr [p] 
              call    

            總結(jié):
            向下類型轉(zhuǎn)換時(shí),強(qiáng)制類型轉(zhuǎn)換都是不行的。你不能作為一個(gè)父親,卻想借著兒子的名號(hào)玩一把年輕,用兒子的名義的名號(hào)去招搖撞騙以為自己是官二代。不過(guò)如果你是兒子,你可以將你的名字換成父親的,去做在父親名字下可以做的事,例如表明自己是官二代撞死人撞不死人在倒回來(lái)繼續(xù)撞。

            當(dāng)類型沒(méi)有虛表的時(shí)候,你不能進(jìn)行向下類型的dynamic_cast,這個(gè)時(shí)候編譯器會(huì)報(bào)錯(cuò):
            //error C2683: 'dynamic_cast' : 'A' is not a polymorphic type.
            不過(guò)奇怪的是向上類型轉(zhuǎn)換的時(shí)候卻沒(méi)這個(gè)錯(cuò)。如果有虛表,還是可以轉(zhuǎn)換的。不過(guò)結(jié)果是0.也就是說(shuō)在想下類型轉(zhuǎn)換的時(shí)候,'dynamic_cast' 是沒(méi)有意義的。

            三、C++類繼承之間轉(zhuǎn)換總結(jié)

            向上類型轉(zhuǎn)換的時(shí)候,你閉著眼睛都可以想出結(jié)果,各種轉(zhuǎn)換關(guān)鍵字的反匯編其實(shí)都是一樣的,都是一個(gè)直接賦值。寫(xiě)代碼的時(shí)候?qū)懖粚?xiě)無(wú)所謂。
            向下類型轉(zhuǎn)換的時(shí)候,你得注意了。為了效率,你就酌情選擇動(dòng)態(tài)還是靜態(tài)轉(zhuǎn)換吧。一般情況靜態(tài)就可以了。
            沒(méi)事不要瞎折騰啊,語(yǔ)言轉(zhuǎn)換不好文檔化時(shí)分析代碼邏輯,也容易出錯(cuò)。

            posted on 2011-06-23 11:49 的筆記 閱讀(469) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C++

            久久国产免费直播| 久久久久久久久久久久中文字幕| 精品人妻久久久久久888| 精品久久亚洲中文无码| 武侠古典久久婷婷狼人伊人| 国产精品美女久久久久AV福利| 久久er国产精品免费观看2| 日本三级久久网| 日本精品久久久久中文字幕| 狠狠色丁香久久综合婷婷| 狠狠色丁香久久婷婷综| 精品视频久久久久| 亚洲国产精品一区二区三区久久 | 久久久女人与动物群交毛片| 蜜臀久久99精品久久久久久小说 | 久久久久久久人妻无码中文字幕爆| 久久久久无码精品国产| 91精品国产91久久久久久蜜臀| 狠狠色伊人久久精品综合网| 免费精品久久久久久中文字幕| 色综合久久夜色精品国产| 久久无码专区国产精品发布| 精品少妇人妻av无码久久| 久久er国产精品免费观看8| 久久国产欧美日韩精品免费| 国产激情久久久久久熟女老人| 无码人妻久久一区二区三区免费丨| 国产成人精品久久免费动漫| 久久久WWW成人免费毛片| 伊人久久大香线蕉综合影院首页| 久久国产精品成人片免费| 亚洲乱亚洲乱淫久久| 久久国产欧美日韩精品| 99国内精品久久久久久久| 精品无码久久久久国产动漫3d| 久久99国产精品二区不卡| 国产69精品久久久久APP下载| 国产精品禁18久久久夂久| 久久婷婷午色综合夜啪| 精品久久久久久| 性欧美丰满熟妇XXXX性久久久 |