• <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>
            隨筆 - 1, 文章 - 9, 評論 - 4, 引用 - 0
            數(shù)據(jù)加載中……

            vft、vptr、thunk

            對于vft(vitrual function table或是vitrual method table)和vptr(vitrual pointer)做一些總結(jié)。

            當類中有虛函數(shù)的時候才會建立vft,這個表里面按照順序(從0開始)和類里面的虛函數(shù)做出對應。
            如果一個類里面有虛函數(shù)(就是有vft),那它就有個vptr。vptr是一個存在在類中的一個隱含指針,這個指針指向的是vft這個表。
            當調(diào)用類中的某個虛函數(shù)的時候,就通過這個指針去找vft里面對應的函數(shù),然后拿來調(diào)用。

            class Base
            {
            public:
                FunctionPointer 
            *__vptr;
                
            virtual void function1() {};
                
            virtual void function2() {};
            };

            class D1: public Base
            {
            public:
                
            virtual void function1() {};
            };

            class D2: public Base
            {
            public:
                
            virtual void function2() {};
            };

            這里顯示的把vptr顯示出來,但實際上是看不見的。


            注意d1和d2的vptr是繼承自base的

            int main()
            {
                D1 cClass;
                Base *pClass = &
            cClass;
                pClass->function1();
            }

            上面的代碼之所以可以執(zhí)行,是因為:pClass指針指向的僅僅是cClass中屬于Base的部分(因為Base是D1的父類),因為vptr原本是在Base中的(雖然看不見),所以pClass是可以調(diào)用vptr的。再由于繼承的關(guān)系,此時的vptr處于D1類中,它指向的是D1的vft,所以pClass->funtion1()這句可以執(zhí)行成功。

            說一個復雜的情況:

            class A
            {
            public:
                
            virtual void a();
            };

            class B : public A
            {
            public:
                
            virtual void a();
                
            virtual void c();
                
            virtual void f();
            };

            class C : public A
            {
            public:
                
            virtual void e();
            };

            class D : public B, public C
            {
            public:
                
            void a();
                
            void g();
            }:

            這里就有點問題,如果單純的vft中按照函數(shù)順序的話。在D這個類中,來自B和來自C這兩個類中的B::c函數(shù)和C::e函數(shù)在他們的類中所在的位置從文本上看都是第二的位置(C類還有個A中繼承的a函數(shù))。那么對于D來說有同一個位置有兩個函數(shù),這時vft必然不能正常實現(xiàn)。在C++中其實D這個類有兩個vft,一個基于B建立,一個基于C建立。當然這種情況下只有在多繼承時才出現(xiàn)。

            那么在實際運行時,首先要把vft的地址(也就是vptr的值)放到寄存器里面,然后要確定用的是哪個類的vft(對于D這個類來說),接著再索引這個函數(shù)表找到函數(shù),最后才根據(jù)地址執(zhí)行函數(shù)。

            也就只對于多繼承這種復雜的情況下,才有上面這么多步驟。對于單繼承,只用找到表,找到索引,找到函數(shù),調(diào)用即可。GCC的thunk在建立vft的時候就確定了到底這個函數(shù)是在哪個對象

            load [object_reg+#VFToffset], table_reg
            load [table_reg
            +#deltaOffset], delta_reg
            load [table_reg
            +#numOffset], method_reg
            add object_reg, delta_reg, object_reg
            call method_reg

            上面的匯編取自一篇論文,VFToffset就是vft的地址偏移,deltaOffset就是多繼承產(chǎn)生的偏移(選哪個類,B還是C),numOffset就是函數(shù)偏移。省去的就是2、4這兩條語句,thunk把這步做了。

            關(guān)于thunk還是有點問題,不是非常明白。

            posted on 2008-12-19 18:09 EiN 閱讀(534) 評論(0)  編輯 收藏 引用 所屬分類: C/C++ and ASM

            无码人妻久久一区二区三区免费丨| 久久93精品国产91久久综合| 久久精品国产99国产精品导航 | 人妻精品久久久久中文字幕一冢本| 97香蕉久久夜色精品国产| 嫩草伊人久久精品少妇AV| 国产成人精品久久综合| 亚洲国产精品无码久久SM| 国内精品久久久久久久久电影网 | 久久久久九国产精品| 综合人妻久久一区二区精品| 久久精品99久久香蕉国产色戒| 久久香蕉一级毛片| 亚洲AV日韩精品久久久久久 | 久久亚洲私人国产精品| 精品人妻伦九区久久AAA片69| 亚洲AV无码一区东京热久久| 久久久久国产精品嫩草影院 | 久久久久99精品成人片三人毛片 | 久久WWW免费人成—看片| 久久久久人妻一区精品色| 久久精品人人做人人爽电影| 青青青青久久精品国产h久久精品五福影院1421| A级毛片无码久久精品免费| 性高湖久久久久久久久AAAAA| 人人狠狠综合久久亚洲婷婷| 精品久久久久香蕉网| 中文无码久久精品| 午夜精品久久久久成人| 精品人妻伦一二三区久久| 777久久精品一区二区三区无码| 嫩草伊人久久精品少妇AV| 国产亚洲综合久久系列| 久久天天躁狠狠躁夜夜96流白浆 | 国产精品亚洲美女久久久| 国产精品久久永久免费| 国产精品美女久久久久久2018| 久久夜色精品国产亚洲| 日韩精品久久久久久久电影蜜臀| 伊人久久无码中文字幕| 久久不见久久见免费视频7|