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

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            C++類對應(yīng)的內(nèi)存結(jié)構(gòu)

            轉(zhuǎn)載自:http://blog.csdn.net/guogangj/archive/2008/01/11/2036785.aspx



            提示1:對“內(nèi)存結(jié)構(gòu)”表示有疑問或不解的,先參考:

            http://blog.csdn.net/guogangj/archive/2007/05/25/1625199.aspx,

            本文使用的表示方法和VC6Memory視圖一致,即:左上表示低位。

             

            提示2:下文提到的“類大小”嚴格上來說是該類經(jīng)過實例化的對象的大小。當然了,光研究長度的話,兩者差別不大,因為:CClassA objAsizeof(CClassA)sizeof(objA)得到的結(jié)果都是一樣的。

             

            一、真空類

            class CNull

            {

            };

            長度:1

            內(nèi)存結(jié)構(gòu):

            ??

            評注:長度其實為0,這個字節(jié)作為內(nèi)容沒有意義,可能每次都不一樣。

             

            二、空類

            class CNull2

            {

            public:

                CNull2(){printf("Construct\n");}

                ~CNull2(){printf("Desctruct\n");}

                void Foo(){printf("Foo\n");}

            };

            長度:1

            內(nèi)存結(jié)構(gòu):

            ??

            評注:同真空類差不多,內(nèi)部的成員函數(shù)并不會影響類大小。

             

            三、簡單類

            class COneMember

            {

            public:

                COneMember(int iValue = 0){m_iOne = iValue;};

            private:

                int m_iOne;

            };

            長度:4

            內(nèi)存結(jié)構(gòu):

            00 00 00 00 //m_iOne

            評注:成員數(shù)據(jù)才影響類大小。

             

            四、簡單繼承

            class CTwoMember:public COneMember

            {

            private:

                int m_iTwo;

            };

            長度:8

            內(nèi)存結(jié)構(gòu):

            00 00 00 00 //m_iOne

            CC CC CC CC //m_iTwo

            評注:子類成員接在父類成員之后。

             

            五、再繼承

            class CThreemember:public CTwoMember

            {

            public:

                CThreemember(int iValue=10) {m_iThree = iValue;};

            private:

                int m_iThree;

            };

            長度:12

            內(nèi)存結(jié)構(gòu):

            00 00 00 00 //m_iOne

            CC CC CC CC //m_iTwo

            0A 00 00 00 //m_iThree

            評注:孫類成員接在子類之后,再再繼承就依此類推了。

             

            六、多重繼承

            class ClassA

            {

            public:

                ClassA(int iValue=1){m_iA = iValue;};

            private:

                int m_iA;

            };

             

            class ClassB

            {

            public:

                ClassB(int iValue=2){m_iB = iValue;};

            private:

                int m_iB;

            };

             

            class ClassC

            {

            public:

                ClassC(int iValue=3){m_iC = iValue;};

            private:

                int m_iC;

            };

             

            class CComplex :public ClassA, public ClassB, public ClassC

            {

            public:

                CComplex(int iValue=4){m_iComplex = iValue;};

            private:

                int m_iComplex;

            };

             

            長度:16

            內(nèi)存結(jié)構(gòu):

            01 00 00 00  //A

            02 00 00 00  //B

            03 00 00 00  //C

            04 00 00 00  //Complex

            評注:也是父類成員先出現(xiàn)在前邊,我想這都足夠好理解。

             

            七、復(fù)雜一些的繼承

            不寫代碼了,怕讀者看了眼花,改畫圖。

            長度:32

            內(nèi)存結(jié)構(gòu):

            01 00 00 00 //A

            02 00 00 00 //B

            03 00 00 00 //C

            04 00 00 00 //Complex

            00 00 00 00 //OneMember

            CC CC CC CC //TwoMember

            0A 00 00 00 //ThreeMember

            05 00 00 00 //VeryComplex

            評注:還是把自己的成員放在最后。

             

            只要沒涉及到“虛”(Virtual),我想沒什么難點,不巧的是“虛”正是我們要研究的內(nèi)容。

             

            八、趁熱打鐵,看“虛繼承”

            class CTwoMember:virtual public COneMember

            {

            private:

                int m_iTwo;

            };

            長度:12

            內(nèi)存結(jié)構(gòu):

            E8 2F 42 00 //指針,指向一個關(guān)于偏移量的數(shù)組,且稱之虛基類偏移量表指針

            CC CC CC CC // m_iTwo

            00 00 00 00 // m_iOne(虛基類數(shù)據(jù)成員)

            評注:virtual讓長度增加了4,其實是多了一個指針,關(guān)于這個指針,確實有些復(fù)雜,別的文章有具體分析,這里就不岔開具體講了,可認為它指向一個關(guān)于虛基類偏移量的數(shù)組,偏移量是關(guān)于虛基類數(shù)據(jù)成員的偏移量。

             

            九、“閉合”虛繼承,看看效果

            長度:24

            內(nèi)存結(jié)構(gòu):

            14 30 42 00 //ClassB的虛基類偏移量表指針

            02 00 00 00 //m_iB

            C4 2F 42 00 //ClassC的虛基類偏移量表指針

            03 00 00 00 //m_iC

            04 00 00 00 //m_iComplex

            01 00 00 00 //m_iA

            評注:和預(yù)料中的一樣,虛基類的成員m_iA只出現(xiàn)了一次,而且是在最后邊。當然了,更復(fù)雜的情況要比這個難分析得多,但虛繼承不是我們研究的重點,我們只需要知道:虛繼承利用一個“虛基類偏移量表指針”來使得虛基類即使被重復(fù)繼承也只會出現(xiàn)一次。

             

            十、看一下關(guān)于static成員

            class CStaticNull

            {

            public:

                CStaticNull(){printf("Construct\n");}

                ~CStaticNull(){printf("Desctruct\n");}

                static void Foo(){printf("Foo\n");}

                static int m_iValue;

            };

            長度:1

            內(nèi)存結(jié)構(gòu):(同CNull2

            評注:可見static成員不會占用類的大小,static成員的存在區(qū)域為靜態(tài)區(qū),可認為它們是“全局”的,只是不提供全局的訪問而已,這跟Cstatic其實沒什么區(qū)別。

             

            十一、帶一個虛函數(shù)的空類

            class CVirtualNull

            {

            public:

                CVirtualNull(){printf("Construct\n");}

                ~CVirtualNull(){printf("Desctruct\n");}

                virtual void Foo(){printf("Foo\n");}

            };

            長度:4

            內(nèi)存結(jié)構(gòu):

            00 31 42 00 //指向虛函數(shù)表的指針(虛函數(shù)表后面簡稱“虛表”)

             

            00423100:(虛表)

            41 10 40 00 //指向虛函數(shù)Foo的指針

             

            00401041:

            E9 78 02 00 00 E9 C3 03  //函數(shù)Foo的內(nèi)容(看不懂)

            評注:帶虛函數(shù)的類長度就增加了4,這個4其實就是個指針,指向虛函數(shù)表的指針,上面這個例子中虛表只有一個函數(shù)指針,值就是“0x00401041”,指向的這個地址就是函數(shù)的入口了。

             

            十二、繼承帶虛函數(shù)的類

            class CVirtualDerived : public CVirtualNull

            {

            public:

                CVirtualDerived(){m_iVD=0xFF;};

                ~CVirtualDerived(){};

            private:

                int m_iVD;

            };

            長度:8

            內(nèi)存結(jié)構(gòu):

            3C 50 42 00 //虛表指針

            FF 00 00 00 //m_iVD

             

            0042503C:(虛表)

            23 10 40 00 //指向虛函數(shù)Foo的指針,如果這時候創(chuàng)建一個CVirtualNull對象,會發(fā)現(xiàn)它的虛表的內(nèi)容跟這個一樣

            評注:由于父類帶了虛函數(shù),子類就算沒有顯式聲明虛函數(shù),虛表還是存在的,虛表存放的位置跟父類不同,但內(nèi)容是同的,也就是對父類虛表的復(fù)制。

             

            十三、子類有新的虛函數(shù)

            class CVirtualDerived: public CVirtualNull

            {

            public:

                CVirtualDerived(){m_iVD=0xFF;};

                ~CVirtualDerived(){};

                virtual void Foo2(){printf("Foo2\n");};

            private:

                int m_iVD;

            };

            長度:8

            內(nèi)存結(jié)構(gòu):

            24 61 42 00 //虛表指針

            FF 00 00 00 //m_iVD

             

            00426124:(虛表)

            23 10 40 00

            50 10 40 00

            評注:虛表還是只有一張,不會因為增加了新的虛函數(shù)而多出另一張來,新的虛函數(shù)的指針將添加在復(fù)制了的虛表的后面。

             

            十四、當純虛函數(shù)(pure function)出現(xiàn)時

            class CPureVirtual

            {

                virtual void Foo() = 0;

            };

             

            class CDerivePV : public CPureVirtual

            {

                void Foo(){printf("vd: Foo\n");};

            };

            長度:4CPureVirtual),4CDerivePV

            內(nèi)存結(jié)構(gòu):

            CPureVirtual:

            (不可實例化)

             

            CDerivePV:

            28 50 42 00 //虛表指針

             

            00425028:(虛表)

            5A 10 40 00 //指向Foo的函數(shù)指針

            評注:帶純虛函數(shù)的類不可實例化,因此列不出其“內(nèi)存結(jié)構(gòu)”,由其派生類實現(xiàn)純虛函數(shù)。我們可以看到CDerivePV雖然沒有virtual聲明,但由于其父類帶virtual,所以還是繼承了虛表,如果CDerivePV有子類,還是這個道理。

             

            十五、虛函數(shù)類的多重繼承

            前面提到:(子類的虛表)不會因為增加了新的虛函數(shù)而多出另一張來,但如果有多重繼承的話情況就不是這樣了。下例中你將看到兩張?zhí)摫怼?span style="LINE-HEIGHT: 24px" lang=EN-US>

            大?。?span style="LINE-HEIGHT: 24px" lang=EN-US>24

            內(nèi)存結(jié)構(gòu)

            F8 50 42 00 //虛表指針

            01 00 00 00 //m_iA

            02 00 00 00 //m_iB

            E8 50 42 00 //虛表指針

            03 00 00 00 //m_iC

            04 00 00 00 //m_iComplex

             

            004250F8:(虛表)

            5A 10 40 00 //FooA

            55 10 40 00 //FooB

            64 10 40 00 //FooComplex

             

            004250E8:(虛表)

            5F 10 40 00 //FooC

            評注:子類的虛函數(shù)接在第一個基類的虛函數(shù)表的后面,所以B接在A后面,Complex接在B后面。基類依次出現(xiàn),子類成員接在最后面,所以m_iComplex位于最后面。

             

            本來還想看看更復(fù)雜些的情況,甚至包括虛繼承和虛函數(shù)同時出現(xiàn)的多重多層繼承情況,但確實有些復(fù)雜了,自己還有些找不到規(guī)律,所以準備之后再補充。


            posted on 2010-03-18 14:34 楊粼波 閱讀(1117) 評論(1)  編輯 收藏 引用

            評論

            # re: C++類對應(yīng)的內(nèi)存結(jié)構(gòu) 2010-06-13 00:34 chaogu

            很有幫助,不過能在解釋一下
            class A{
            private:
            char charMember;
            short shortMember;
            int intMember;
            }
            那就無敵了。

            如果再跟struct比較一下,那頂?shù)娜硕嗔恕?br>如果順便解釋一下struct中的pading和union
            那你說這篇文章是什么?  回復(fù)  更多評論   

            久久亚洲精品国产精品婷婷| 蜜臀久久99精品久久久久久小说| 精品久久久久久久中文字幕| 久久亚洲国产精品五月天婷| 国产精品久久久久免费a∨| 久久99久久99精品免视看动漫| 中文精品久久久久国产网址| 青草久久久国产线免观| 97精品国产91久久久久久| 日韩欧美亚洲综合久久影院Ds | 国产精品成人99久久久久 | 久久精品国产亚洲AV影院| 久久免费小视频| 人妻精品久久无码专区精东影业| 热RE99久久精品国产66热| 情人伊人久久综合亚洲| 亚洲乱码中文字幕久久孕妇黑人| 日韩久久久久中文字幕人妻| 91久久精品国产成人久久| 精品久久久无码人妻中文字幕豆芽 | 一本色道久久综合| 精品国产综合区久久久久久| 好久久免费视频高清| 日韩人妻无码一区二区三区久久 | 亚洲国产精品无码久久SM| 久久免费大片| 精品久久久无码中文字幕| 久久免费高清视频| 99热成人精品热久久669| 色8久久人人97超碰香蕉987| 欧美午夜精品久久久久免费视| 亚洲国产精品嫩草影院久久| 精品久久国产一区二区三区香蕉 | 波多野结衣久久精品| 一级做a爰片久久毛片看看 | 无码人妻精品一区二区三区久久| 国产成人综合久久精品红| 囯产精品久久久久久久久蜜桃| 狠狠色丁香久久婷婷综合图片| 狠狠色丁香久久婷婷综合_中| 久久久久久久久久久久久久|