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

            的筆記

            隨時隨地編輯

            Dynamic、Static、Reinterpret、Const Cast

            一、向上類型轉換


            情形一:
            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()的代碼,這個編譯器自動幫我們加上去的代碼,如果沒有虛報是不會有的。
             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
            只是在上文改動一處:去掉A::fun()的聲明virtual。

            Disassembly對比
                              左:無virtual聲明                                                           右:有virtual聲明

            結論: 無論哪種cast,向上類型都一樣。函數調用只與虛表有關。向上類型轉換是最常見的一種轉換,常見的大部分代碼都是用"向上類型轉換+虛函數"這種黃金組合完成一些c++類庫,例如MFC,QT,OGRE.這種轉換很符合常規,基本不會出錯。

            二、向下類型轉換

            情形一:

            C++ CODE

            A和B的聲明同上,只是改變A::fun()是虛函數。
             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()不是虛函數。
                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    

            總結:
            向下類型轉換時,強制類型轉換都是不行的。你不能作為一個父親,卻想借著兒子的名號玩一把年輕,用兒子的名義的名號去招搖撞騙以為自己是官二代。不過如果你是兒子,你可以將你的名字換成父親的,去做在父親名字下可以做的事,例如表明自己是官二代撞死人撞不死人在倒回來繼續撞。

            當類型沒有虛表的時候,你不能進行向下類型的dynamic_cast,這個時候編譯器會報錯:
            //error C2683: 'dynamic_cast' : 'A' is not a polymorphic type.
            不過奇怪的是向上類型轉換的時候卻沒這個錯。如果有虛表,還是可以轉換的。不過結果是0.也就是說在想下類型轉換的時候,'dynamic_cast' 是沒有意義的。

            三、C++類繼承之間轉換總結

            向上類型轉換的時候,你閉著眼睛都可以想出結果,各種轉換關鍵字的反匯編其實都是一樣的,都是一個直接賦值。寫代碼的時候寫不寫無所謂。
            向下類型轉換的時候,你得注意了。為了效率,你就酌情選擇動態還是靜態轉換吧。一般情況靜態就可以了。
            沒事不要瞎折騰啊,語言轉換不好文檔化時分析代碼邏輯,也容易出錯。

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

            伊人热热久久原色播放www| 亚洲狠狠婷婷综合久久久久| 久久久亚洲裙底偷窥综合| 久久精品无码一区二区日韩AV | 国产伊人久久| 久久久久亚洲?V成人无码| 久久精品国产精品青草| 麻豆精品久久久一区二区| 精品久久人人做人人爽综合| …久久精品99久久香蕉国产 | 麻豆精品久久久一区二区| 99久久er这里只有精品18| 91精品国产91久久久久久| 久久影院午夜理论片无码| 精品国产一区二区三区久久久狼| 伊人久久精品无码av一区| 久久久久九九精品影院| 国产成人精品综合久久久| 伊人久久精品无码二区麻豆| 亚洲中文久久精品无码| 久久人爽人人爽人人片AV | 日本WV一本一道久久香蕉| 国产一久久香蕉国产线看观看| 久久狠狠高潮亚洲精品| 漂亮人妻被中出中文字幕久久 | 欧美亚洲色综久久精品国产| 久久久一本精品99久久精品66| 国产精品九九九久久九九| 国产精品免费久久| 一本色道久久综合狠狠躁篇| 亚洲国产另类久久久精品小说 | 久久99久久99精品免视看动漫| 亚洲va久久久噜噜噜久久狠狠| 国产精品久久成人影院| 国产午夜精品久久久久九九电影| 亚洲v国产v天堂a无码久久| 亚洲国产精品久久66| 一本大道久久东京热无码AV| 久久人妻少妇嫩草AV无码专区| 99久久国产免费福利| 久久久久久久精品成人热色戒|