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

            久久久久国产视频电影| 合区精品久久久中文字幕一区| 亚洲人AV永久一区二区三区久久 | 久久亚洲精品国产精品婷婷| 久久久99精品成人片中文字幕| 一本色综合久久| 久久精品人人做人人爽电影蜜月| 久久综合国产乱子伦精品免费| 国内精品久久久久影院免费| 久久久久亚洲AV成人网人人软件| 久久精品国产99久久久古代| 久久久精品午夜免费不卡| 亚洲а∨天堂久久精品| 日产精品久久久久久久| 久久天天躁狠狠躁夜夜不卡| 亚洲女久久久噜噜噜熟女| 国产精品美女久久久免费| 欧洲人妻丰满av无码久久不卡 | 色综合久久久久| 国内精品伊人久久久久妇| 精品免费tv久久久久久久| 久久久久久午夜精品| 久久99国产一区二区三区| 99久久综合国产精品二区| 国产精品久久久久免费a∨| 欧美激情精品久久久久| 青青草原精品99久久精品66| 久久人人爽人人澡人人高潮AV| 99久久精品影院老鸭窝| 国产A三级久久精品| 久久久精品久久久久久 | 国产精品熟女福利久久AV| 熟妇人妻久久中文字幕| 伊人久久大香线蕉综合5g| 久久久久亚洲AV无码专区桃色| 99精品久久精品| 97久久国产亚洲精品超碰热| 性欧美大战久久久久久久久 | 无遮挡粉嫩小泬久久久久久久 | 四虎国产精品免费久久久| 狠狠色丁香久久婷婷综合五月|