亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        C++語言中的虛函數(shù)研究

        2010-04-12 00:00:00徐啟豐萬玉成
        現(xiàn)代電子技術(shù) 2010年4期

        摘 要:虛函數(shù)是面向?qū)ο蟮腃++語言中的一個非常重要的概念。它充分體現(xiàn)了面向?qū)ο笏枷胫械睦^承和多態(tài)性這兩大特性,動態(tài)綁定是C++中實現(xiàn)多態(tài)的一個重要途徑,虛函數(shù)是動態(tài)綁定的基礎(chǔ)。通過深入分析VC++編譯器實現(xiàn)虛函數(shù)的匯編代碼。給出在繼承下的實現(xiàn)模型,并結(jié)合實例,在匯編語言層次研究了多態(tài)性的實現(xiàn)機理,揭示了虛函數(shù)和動態(tài)綁定的本質(zhì)。

        關(guān)鍵詞:虛函數(shù);多態(tài)性;綁定;構(gòu)造函數(shù)

        中圖分類號:TP312文獻標識碼:A

        文章編號:1004-373X(2010)04-154-03

        Study of Virtual Function in C++

        XU Qifeng,HU Yong,WANG Yucheng

        (Xuzhou Air Force College,Xuzhou,221000,China)

        Abstract:Virtual Function is an important concept of object oriented language C++.It presents the Inheritance and Polymorphism of the idea in object oriented language,dynamic binding is an important approach to realize polymorphism in C++ and virtual function is its foundation,this paper investigates the realization mechanism of virtual function in assemble language in VC++.According to inheritance relationship,the realize model of polymorphism is studied by example and in assemble language,and reveals the essence of virtual function and dynamic binding .

        Keywords:virtual function;polymorphism;bind;constructor

        0 引 言

        多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計語言繼數(shù)據(jù)抽象和繼承之后的第三個基本特征[1,2],在C++語言中,多態(tài)性是用虛函數(shù)來實現(xiàn)的[3,4],如果某類中的一個成員函數(shù)被說明為虛函數(shù),該類被稱為多態(tài)類,這就意味著該成員函數(shù)在派生類中可以有不同的實現(xiàn),當用一個基類指針或引用指向一個繼承類對象調(diào)用虛函數(shù)的時候,實際調(diào)用的是繼承類版本的虛函數(shù)。

        綁定是指把函數(shù)定義體與函數(shù)調(diào)用相聯(lián)接的過程,按照綁定所進行的階段不同,可分為兩種不同的綁定方法:靜態(tài)綁定和動態(tài)綁定[5,6],靜態(tài)綁定是傳統(tǒng)的過程式程序設(shè)計語言所使用的方法,即函數(shù)定義體和函數(shù)調(diào)用間的聯(lián)接發(fā)生在編譯連接階段,這種聯(lián)編又稱早期綁定,因為綁定過程是在程序開始運行之前完成的。靜態(tài)綁定的優(yōu)點是有效性,即速度快,所需內(nèi)存小,易實現(xiàn)代碼優(yōu)化,主要缺點是缺乏靈活性。與靜態(tài)綁定相對應(yīng)的是動態(tài)綁定,動態(tài)綁定意味著函數(shù)調(diào)用與函數(shù)定義體的聯(lián)接是在程序運行是進行的,即在編譯時,編譯器不能確定某一對象實體與具體那個函數(shù)調(diào)用相聯(lián)接,必須在運行時刻根據(jù)上下文關(guān)系來確定[7]。動態(tài)綁定也叫晚期綁定,動態(tài)綁定以效率性來換取靈活性。在C++語言中,當使用基類指針或引用調(diào)用虛函數(shù)采用的就是動態(tài)綁定的方式[8],即根據(jù)基類指針或引用的動態(tài)類型(指針或引用所指向或引用對象的類型)選擇相應(yīng)的虛函數(shù)版本,而不是根據(jù)基類指針或引用的靜態(tài)類型(聲明指針或引用時所使用的類型)來選擇函數(shù)版本,從而給程序帶來了多態(tài)性[9-11]。

        1 虛函數(shù)的實現(xiàn)機理

        下面從一個具體的程序來分析虛函數(shù)的實現(xiàn)機理,程序如下,在Visual C++ 6.0編譯器下運行。

        #include

        using namespace std;

        class CBase

        {

        public:

        int Base_x;

        virtual void vFun1();

        virtual void vFun2();

        void Fun3();

        };

        void CBase::vFun1()

        {

        cout << \"CBase::vFun1()\"<

        }

        void CBase::vFun2()

        {

        cout << \"CBase::vFun2()\"<

        }

        void CBase::Fun3()

        {

        cout << \"CBase::Fun3()\"<

        }

        class CDerived:public CBase

        {

        int Derived_x;

        int Derived_y;

        void vFun2();

        };

        void CDerived::vFun2()

        {

        cout << \"CDerived::vFun2()\"<

        }

        void main()

        {

        CBase * pBase;

        CDerived Derived;

        pBase = Derived;

        pBase->vFun1();

        pBase->vFun2();

        pBase->Fun3();

        }

        該程序定義了兩個類:CBase 類和他的派生類CDerived類。CBase類中有兩個虛函數(shù) vFun1()和vFun2(),另外還有一個非虛函數(shù)Fun3(),在CDerived類中改寫了vFun2()的定義,最后,在main()函數(shù)中,用基類Cbase定義了一個指針pBase,然后將定義好的Cderived類的一個對象的地址賦給pBase,即指針pBase的靜態(tài)類型是Cbase,動態(tài)類型是Cderived,接下來用pBase對vFun1(),vFun2(),F(xiàn)un3()分別進行調(diào)用,輸出結(jié)果如下:

        CBase::vFun1()

        CDerived::vFun2()

        CBase::Fun3()

        下面通過分析編譯器生成的匯編代碼來分析虛函數(shù)的實現(xiàn)機理,首先分析對Fun3()函數(shù)調(diào)用生成的匯編代碼:

        pBase->Fun3();

        這條語句對應(yīng)的匯編代碼如下:

        mov ecx,DWORD PTR _pBaseMYM[ebp]

        call ?Fun3@CBase@@QAEXXZ; CBase::Fun3

        從上面的代碼可以看出,因為Fun3()是非虛擬的成員函數(shù),不論pBase 指針所指向?qū)ο蟮念愋褪鞘裁?,對Fun3()的調(diào)用是依據(jù)pBase的靜態(tài)類型Cbase 來綁定相應(yīng)的函數(shù)定義體的,所以pBase->Fun3()最終轉(zhuǎn)化成對CBase::Fun3()的調(diào)用。這就是前面所提到的靜態(tài)綁定。下面在看看編譯器為pBase->vFun2()這條語句所生成的匯編代碼:

        mov eax,DWORD PTR _pBaseMYM[ebp]

        mov edx,DWORD PTR [eax]

        mov esi,esp

        mov ecx,DWORD PTR _pBaseMYM[ebp]

        call DWORD PTR [edx+4]

        cmp esi,esp

        call __chkesp

        _pBaseMYM[ebp]就是pBase的實際值,即Derived對象的地址。對vFun2()的調(diào)用最終轉(zhuǎn)化為call DWORD PTR [edx+4],從代碼可以看出,edx的值就是Derived對象的地址。為了弄清楚[edx+4]代表什么,需要分析Derived對象的內(nèi)存空間的布局情況,首先看一下Derived對象的構(gòu)造函數(shù)的代碼,下面摘錄了其中的關(guān)鍵代碼:

        mov DWORD PTR _thisMYM[ebp],ecx

        mov ecx,DWORD PTR _thisMYM[ebp]

        call ??0CBase@@QAE@XZ ; CBase::CBase

        mov eax,DWORD PTR _thisMYM[ebp]

        mov DWORD PTR [eax],OFFSET FLAT:??_7CDerived@@6B@ ; CDerived::′vftable′

        mov eax,DWORD PTR _thisMYM[ebp]

        Cbase類的構(gòu)造函數(shù)相關(guān)代碼如下所示:

        mov DWORD PTR _thisMYM[ebp],ecx

        mov eax,DWORD PTR _thisMYM[ebp]

        mov DWORD PTR [eax],OFFSET FLAT:??_7CBase@@6B@ ; CBase::′vftable′

        mov eax,DWORD PTR _thisMYM[ebp]

        從上面的代碼可以看出,編譯器生成的vftable地址即vptr插入到存放對象內(nèi)存區(qū)的首地址(即this指針指向的地方)的代碼。所以說,帶有虛函數(shù)的對象在構(gòu)造時,涉及到vftable,而vftable在CONST區(qū)定義,代碼如下所示:

        CONST SEGMENT

        ??_7CDerived@@6B@

        DDFLAT:?vFun1@CBase@@UAEXXZ; CDerived::′vftable′

        DDFLAT:?vFun2@CDerived@@EAEXXZ

        CONST ENDS

        2 結(jié) 語

        從上面的代碼可以看出,vftable其實就是一個容納虛函數(shù)的地址的表格[12],Cderived的虛函數(shù)表格里面有從基類繼承而來的虛函數(shù)vFun1()和改寫了定義的vFun2()的地址。Cderived的構(gòu)造函數(shù)調(diào)用了基類Cbase的構(gòu)造函數(shù),CBase的構(gòu)造函數(shù)也有初始化虛函數(shù)指針的過程,但由于Cderived的構(gòu)造函數(shù)初始化虛函數(shù)指針在調(diào)用CBase的構(gòu)造函數(shù)之后,因此最終的虛函數(shù)表容納的是派生類的虛函數(shù)的地址,結(jié)合前面編譯器為pBase->vFun2()語句所生成的匯編代碼,可以得出如下結(jié)論:

        (1) 編譯器必須為多態(tài)類的每個對象增加一個vptr指針,由多態(tài)類的構(gòu)造函數(shù)負責vptr的初始化;

        (2) 每個多態(tài)類至少增加一個vftable表到程序的數(shù)據(jù)區(qū),vftable就是一張指向虛擬函數(shù)的函數(shù)指針表;

        (3) 每個虛函數(shù)的調(diào)用被編譯器轉(zhuǎn)化通過查找vftable來定位函數(shù)地址(需要額外的機器指令),如pBase->vFun2()將會轉(zhuǎn)化為(*pBase->vptr[2])(pBase)。

        以上結(jié)論是針對visual C++ 6.0編譯器而言的,對于其他編譯器,具體實現(xiàn)雖不完全相同,但都大同小異。如gnu C++編譯器就把指向vtable的指針放在對象尾部而不是頭部。

        參考文獻

        [1]藍雯飛.C++語言中的面向?qū)ο筇卣魈接慬J].計算機工程與應(yīng)用,2000,36(9):91-92.

        [2]夏承遺,董玉濤,趙德新,等.C++中虛函數(shù)的實現(xiàn)機制[J].天津理工學(xué)院學(xué)報,2004,20(3):65-67.

        [3]Bjarne Stroustrup.The C++ Programming Language[M].Special Edition(影印版).北京:高等教育出版社,2001.

        [4]張昀.C++中的多態(tài)性研究[J].教育技術(shù)導(dǎo)刊,2009,18(2):65-66.

        [5]Terrence W Pratt.程序設(shè)計語言:設(shè)計與實現(xiàn)[M].傅育熙,譯.北京:電子工業(yè)出版社,2001.

        [6]趙紅超,方金云,唐志敏.C++的動態(tài)多態(tài)和靜態(tài)多態(tài)[J].計算機工程,2005,31(20):72-73,87.

        [7]Bjarne Stroustrup.C++的設(shè)計與演化[M].裘宗燕,譯.北京:機械工業(yè)出版社,2002.

        [8]藍雯飛,陸際光.C++面向?qū)ο蟪绦蛟O(shè)計中的多態(tài)性研究[J].計算機工程與應(yīng)用,2000,36(8):97-98.

        [9]Stanley B Lippman.Inside the C++ Object Model[M].侯捷,譯.武漢:華中科技大學(xué)出版社,2001.

        [10]張亞鵬.關(guān)于C++中虛函數(shù)的幾個問題[J].赤峰學(xué)院學(xué)報:自然科學(xué)版,2006(2):132-133.

        [11]和力,吳麗賢.關(guān)于C++虛函數(shù)底層實現(xiàn)機制的研究與分析[J].計算機工程與設(shè)計,2008,29(10):2 705-2 707.

        [12]Scott Mayers.More Effective C++ [M].2nd Edition.Addi-sion Wesley Lonman Inc.,1996.

        [13]袁亞麗,肖桂云.C++中虛函數(shù)的實現(xiàn)技術(shù)研究[J].河北北方學(xué)院學(xué)報:自然科學(xué)版,2006,22(5):67-69,75.

        [14]藍雯飛.C++中的多態(tài)性及其應(yīng)用[J].計算機時代,1998(7):15-16.

        99久久超碰中文字幕伊人| 朝鲜女人大白屁股ass| 免费观看黄网站| 亚洲国产成人AⅤ片在线观看| 蜜臀av国内精品久久久人妻| 男女调情视频在线观看| 无码视频在线观看| 成人片黄网站色大片免费观看app| 国产成人久久精品77777综合| 日本国产一区二区在线| 四虎成人精品国产永久免费无码| 久久精品一区二区三区av| 久久久亚洲精品午夜福利| 宅男天堂亚洲一区二区三区| 狠狠摸狠狠澡| 久久精品中文字幕一区| 一区在线播放| 亚洲国产综合人成综合网站| 特黄做受又硬又粗又大视频小说| 无码AV高潮喷水无码专区线 | 在线视频一区二区亚洲| 日韩人妻久久中文字幕| 亚洲精品久久一区二区三区777| 日韩a∨精品日韩在线观看| 午夜人妻中文字幕福利| 亚洲中文字幕久久精品一区| 97高清国语自产拍| 亚洲中文字幕无码卡通动漫野外| 偷拍熟女露出喷水在线91| 久久精品国产字幕高潮| 亚洲成a人v欧美综合天堂麻豆| 国产aⅴ丝袜旗袍无码麻豆 | 九色精品国产亚洲av麻豆一| 在线观看视频日本一区二区| 久久国产精品精品国产色婷婷| 免费观看一区二区| 色综合久久丁香婷婷| 久久一二三四区中文字幕| av影院在线免费观看不卡| 免费国产裸体美女视频全黄| 女人的天堂av免费看|