真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么

靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么?針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供昌江黎族網(wǎng)站建設(shè)、昌江黎族做網(wǎng)站、昌江黎族網(wǎng)站設(shè)計(jì)、昌江黎族網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、昌江黎族企業(yè)網(wǎng)站模板建站服務(wù),十年昌江黎族做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

什么是多態(tài)

從字面上理解就是多種形態(tài)的意思。而多態(tài)一詞最初源自希臘語,其含義便是“多種形式”,意思是是具有多種形式或形態(tài)的情形,在C++語言中多態(tài)有著更廣泛的含義。在C++ primer一書中把具有繼承關(guān)系的多個(gè)類型稱為多態(tài)類型,因?yàn)槲覀兡苁褂眠@些類型的“多種形式”而無須在意它們的差異。百度百科上提到在面向?qū)ο笳Z言中,接口的多種不同的實(shí)現(xiàn)方式即為多態(tài)。引用Charlie Calverts對(duì)多態(tài)的描述——多態(tài)性是允許你將父對(duì)象設(shè)置成為一個(gè)或更多的他的子對(duì)象相等的技術(shù),賦值之后,父對(duì)象就可以根據(jù)當(dāng)前賦值給它的子對(duì)象的特性以不同的方式運(yùn)作。簡(jiǎn)單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。多態(tài)性在Object Pascal和C++中都是通過虛函數(shù)實(shí)現(xiàn)的。
只從概念描述是無法深刻清晰的理解它的,下面我們就具體分析一下。

1、對(duì)象類型

這里所說的對(duì)象類型可以用下面的圖來體現(xiàn):靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么我們通過代碼舉例說明一下

 1 class Derived1:public Base 2 {}; 3 class Derived2:public Base 4 {}: 5 int main() 6 { 7      Derived1* p1 = new Derived1; 8      Base = p1; 9      Derived2* p2 = new Derived1;10      Base = p2;11      return = p212 }

靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么靜態(tài)類型在編譯時(shí)總是已知的,他是變量聲明時(shí)的類型或表達(dá)式生成的類型;動(dòng)態(tài)類型則是變量或表達(dá)式表示的內(nèi)存中的對(duì)象的類型。動(dòng)態(tài)類型直到運(yùn)行時(shí)才可知道。

2、靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)

靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài)的區(qū)別其實(shí)用下面的圖就可以體現(xiàn): 靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么

靜態(tài)多態(tài)

靜態(tài)多態(tài)也稱為靜態(tài)綁定或早綁。編譯器在編譯期間完成的, 編譯器根據(jù)函數(shù)實(shí)參的類型(可能會(huì)進(jìn)行隱式類型轉(zhuǎn)換) , 可推斷出要調(diào)用那個(gè)函數(shù), 如果有對(duì)應(yīng)的函數(shù)就調(diào)用該函數(shù), 否則出現(xiàn)編譯錯(cuò)誤。

 1 int Add(int left,int right) 2 { 3      return left + right; 4 } 5 float Add(float left, float right) 6 { 7      return left + right; 8 } 9 int main()10 {   
11     cout<

這里我把重載歸為了靜態(tài)多態(tài)。重載的實(shí)現(xiàn)是:編譯器根據(jù)函數(shù)不同的參數(shù)表,對(duì)同名函數(shù)的名稱做修飾,然后這些同名函數(shù)就成了不同的函數(shù)(至少對(duì)于編譯器來說是這樣的)。函數(shù)的調(diào)用,在編譯器間就已經(jīng)確定了,是靜態(tài)的(記?。菏庆o態(tài))。也就是說,它們的地址在編譯期就綁定了(早綁定)。正是由于重載的這種性質(zhì),也有結(jié)論認(rèn)為:重載只是一種語言特性,與多態(tài)無關(guān),與面向?qū)ο笠矡o關(guān)。基于面向?qū)ο髞碚f重載的概念并不屬于“面向?qū)ο缶幊獭?。但是多態(tài)性又是一個(gè)比較廣泛的概念。這里為了便于理解先不去深度分析它們的區(qū)別,等多態(tài)的其它部分具體分析完畢,我們?cè)賮碚f。

動(dòng)態(tài)多態(tài)

動(dòng)態(tài)綁定: 在程序執(zhí)行期間(非編譯期) 判斷所引 用對(duì)象的實(shí)際類型, 根據(jù)其實(shí)際類型調(diào)用相應(yīng)的方法。使用virtual關(guān)鍵字修飾類的成員 函數(shù)時(shí), 指明該函數(shù)為虛函數(shù), 派生類需要重新實(shí)現(xiàn), 編譯器將實(shí)現(xiàn)動(dòng)態(tài)綁定。

              FunTest1(         cout <<  <<       FunTest2(         cout <<  <<        FunTest3(         cout <<  <<        FunTest4(         cout <<  <<    CDerived :              FunTest1(         cout <<  <<        FunTest2(         cout <<  <<       FunTest3( _iTest1) { cout <<  <<        FunTest4( _iTest1,          cout <<  <<        CBase* pBase =      pBase->FunTest1(     pBase->FunTest2(     pBase->FunTest3(     pBase->FunTest4(        }

靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么當(dāng)我們使用基類的指針或引用調(diào)用基類中定義的一個(gè)函數(shù)時(shí)時(shí),我們并不知道該函數(shù)真正的對(duì)象是什么類型,因?yàn)樗赡苁且粋€(gè)基類的對(duì)象,也可能是一個(gè)派生類的對(duì)象。如果該函數(shù)是虛函數(shù),則直到運(yùn)行時(shí)才會(huì)知道到及執(zhí)行哪個(gè)版本,判斷的依據(jù)是引用或指針?biāo)壎ǖ膶?duì)象的真實(shí)類型。

析構(gòu)函數(shù)、靜態(tài)類型函數(shù)、友元函數(shù)、內(nèi)聯(lián)函數(shù)與虛函數(shù)

        CTest&  =( CTest&       *     fri end voi d FunTestFri end() ;
12 }

什么是虛函數(shù)

其實(shí)在前面的虛擬繼承中我們已經(jīng)用到了虛函數(shù)這個(gè)概念,在那里我們是為了解決菱形普通繼承中訪問二義性的問題,但在多態(tài)中,他有更大的作用。百度百科中對(duì)虛函數(shù)是這么說的:在某基類中聲明為 virtual 并在一個(gè)或多個(gè)派生類中被重新定義的成員函數(shù),用法格式為:virtual 函數(shù)返回類型 函數(shù)名(參數(shù)表) {函數(shù)體};實(shí)現(xiàn)多態(tài)性,通過指向派生類的基類指針或引用,訪問派生類中同名覆蓋成員函數(shù)。形象的解釋為“求同存異”,它的作用就是實(shí)現(xiàn)多態(tài)性。

簡(jiǎn)單地說,那些被virtual關(guān)鍵字修飾的成員函數(shù),就是虛函數(shù)。虛函數(shù)的作用,用專業(yè)術(shù)語來解釋就是實(shí)現(xiàn)多態(tài)性(Polymorphism),多態(tài)性是將接口與實(shí)現(xiàn)進(jìn)行分離;用形象的語言來解釋就是實(shí)現(xiàn)以共同的方法,但因個(gè)體差異,而采用不同的策略。

 1 class A 2 { 3     public: 4         virtual void print(){cout<<"This is A"<print();18     p2->print();19     return 0;20 }

毫無疑問,class A的成員函數(shù)print()已經(jīng)成了虛函數(shù),那么class B的print()成了虛函數(shù)了嗎?回答是Yes,我們只需在把基類的成員函數(shù)設(shè)為virtual,其派生類的相應(yīng)的函數(shù)也會(huì)自動(dòng)變?yōu)樘摵瘮?shù)。所以,class B的print()也成了虛函數(shù)。那么對(duì)于在派生類的相應(yīng)函數(shù)前是否需要用virtual關(guān)鍵字修飾,那就是你自己的問題了(語法上可加可不加,不加的話編譯器會(huì)自動(dòng)加上,但為了閱讀方便和規(guī)范性,建議加上)。

運(yùn)行代碼,輸出的結(jié)果是This is A和This is B。

總結(jié):指向基類的指針在操作它的多態(tài)類對(duì)象時(shí),會(huì)根據(jù)不同的類對(duì)象,調(diào)用其相應(yīng)的函數(shù),這個(gè)函數(shù)就是虛函數(shù)。

析構(gòu)函數(shù)與虛函數(shù)

當(dāng)在析構(gòu)函數(shù)前面加virtual關(guān)鍵字時(shí)報(bào)錯(cuò):靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么,我們來分析一下原因。

1、虛函數(shù)的執(zhí)行依賴于虛函數(shù)表。而虛函數(shù)表在構(gòu)造函數(shù)中進(jìn)行初始化工作,即初始化vptr,讓他指向正確的虛函數(shù)表。而在構(gòu)造對(duì)象期間,虛函數(shù)表還沒有被初 始化,將無法進(jìn)行。

2、構(gòu)造一個(gè)對(duì)象的時(shí)候,必須知道對(duì)象的實(shí)際類型,而虛函數(shù)行為是在運(yùn)行期間確定實(shí)際類型的。而在構(gòu)造一個(gè)對(duì)象時(shí),由于對(duì)象還未構(gòu)造成功。編譯器無法知道對(duì)象 的實(shí)際類型,是該類本身,還是該類的一個(gè)派生類,或是更深層次的派生類。無法確定。

虛函數(shù)的意思就是開啟動(dòng)態(tài)綁定,程序會(huì)根據(jù)對(duì)象的動(dòng)態(tài)類型來選擇要調(diào)用的方法。然而在構(gòu)造函數(shù)運(yùn)行的時(shí)候,這個(gè)對(duì)象的動(dòng)態(tài)類型還不完整,沒有辦法確定它到底是什么類型,故構(gòu)造函數(shù)不能動(dòng)態(tài)綁定。(動(dòng)態(tài)綁定是根據(jù)對(duì)象的動(dòng)態(tài)類型而不是函數(shù)名,在調(diào)用構(gòu)造函數(shù)之前,這個(gè)對(duì)象根本就不存在,它怎么動(dòng)態(tài)綁定?)
編譯器在調(diào)用基類的構(gòu)造函數(shù)的時(shí)候并不知道你要構(gòu)造的是一個(gè)基類的對(duì)象還是一個(gè)派生類的對(duì)象。

靜態(tài)類型函數(shù)與虛函數(shù)

當(dāng)我們?cè)陟o態(tài)類型函數(shù)前加virtual關(guān)鍵字時(shí)報(bào)錯(cuò):靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么分析:

1、 static成員不屬于任何類對(duì)象或類實(shí)例,所以即使給此函數(shù)加上virutal也是沒有任何意義的。

2、static函數(shù)沒有this指針,并且不會(huì)進(jìn)入虛函數(shù)表的。當(dāng)通過指針或者引用調(diào)用時(shí)根本無法把this指針傳遞給static函數(shù),從而無法體現(xiàn)出多態(tài)。靜態(tài)成員函數(shù)與普通成員函數(shù)的差別就在于缺少this指針,沒有這個(gè)this指針自然也就無從知道name是哪一個(gè)對(duì)象的成員了。

友元函數(shù)與虛函數(shù)

當(dāng)我們?cè)谟言瘮?shù)前加virtual關(guān)鍵字時(shí)報(bào)錯(cuò):靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么

因?yàn)?code>C++不支持友元函數(shù)的繼承,對(duì)于沒有繼承特性的函數(shù)沒有虛函數(shù)的說法。

內(nèi)聯(lián)成員函數(shù)與虛函數(shù)

內(nèi)聯(lián)函數(shù)就是為了在代碼中直接展開,減少函數(shù)調(diào)用花費(fèi)的代價(jià),虛函數(shù)是為了在繼承后對(duì)象能夠準(zhǔn)確的執(zhí)行自己的動(dòng)作,這是不可能統(tǒng)一的。(再說了,inline函數(shù)在編譯時(shí)被展開,虛函數(shù)在運(yùn)行時(shí)才能動(dòng)態(tài)的邦定函數(shù))

賦值運(yùn)算符的重載與虛函數(shù)

當(dāng)我們把賦值運(yùn)算符的重載定義為虛函數(shù)時(shí)編譯可以通過,但是一般不建議這么做雖然可以將operator=定義為虛函數(shù), 但使用時(shí)容易混淆。

1、無法給派生類的自有成員賦值;

2、調(diào)用虛函數(shù)要進(jìn)行查虛表等一系列操作,效率下降。

析構(gòu)函數(shù)與虛函數(shù)

析構(gòu)函數(shù)設(shè)為虛函數(shù)的作用:在類的繼承中,如果有基類指針指向派生類,那么用基類指針delete時(shí),如果不定義成虛函數(shù),派生類中派生的那部分無法析構(gòu)。

 1 #include  2 #include  3 class A 4 { 5     public: 6     A(); 7     virtual~A(); 8 }; 9     A::A()10     {}11     A::~A()12     {13     printf("Delete class APn");14     }15 class B : public A16 {17     public:18     B();19     ~B();20 };21     B::B()22     { }23     B::~B()24     {25     printf("Delete class BPn");26     }27 int main(int argc, char* argv[])28 {29     A *b=new B;30     delete b;31     return 0;32 }

輸出結(jié)果為:Delete class B     Delete class A
如果把A的virtual去掉:那就變成了Delete class A也就是說不會(huì)刪除派生類里的剩余部分內(nèi)容,也即不調(diào)用派生類的虛函數(shù)

析構(gòu)函數(shù)總結(jié):

1. 如果我們定義了一個(gè)構(gòu)造函數(shù),編譯器就不會(huì)再為我們生成默認(rèn)構(gòu)造函數(shù)了。
2. 編譯器生成的析構(gòu)函數(shù)是非虛的,除非是一個(gè)子類,其父類有個(gè)虛析構(gòu),此時(shí)的函數(shù)虛特性來自父類。
3. 有虛函數(shù)的類,幾乎可以確定要有個(gè)虛析構(gòu)函數(shù)。
4. 如果一個(gè)類不可能是基類就不要申明析構(gòu)函數(shù)為虛函數(shù),虛函數(shù)是要耗費(fèi)空間的。
5. 析構(gòu)函數(shù)的異常退出會(huì)導(dǎo)致析構(gòu)不完全,從而有內(nèi)存泄露。最好是提供一個(gè)管理類,在管理類中提供一個(gè)方法來析構(gòu),調(diào)用者再根據(jù)這個(gè)方法的結(jié)果決定下一步的操作。
6. 在構(gòu)造函數(shù)不要調(diào)用虛函數(shù)。在基類構(gòu)造的時(shí)候,虛函數(shù)是非虛,不會(huì)走到派生類中,既是采用的靜態(tài)綁定。顯然的是:當(dāng)我們構(gòu)造一個(gè)子類的對(duì)象時(shí),先調(diào)用基類的構(gòu)造函數(shù),構(gòu)造子類中基類部分,子類還沒有構(gòu)造,還沒有初始化,如果在基類的構(gòu)造中調(diào)用虛函數(shù),如果可以的話就是調(diào)用一個(gè)還沒有被初始化的對(duì)象,那是很危險(xiǎn)的,所以C++中是不可以在構(gòu)造父類對(duì)象部分的時(shí)候調(diào)用子類的虛函數(shù)實(shí)現(xiàn)。但是不是說你不可以那么寫程序,你這么寫,編譯器也不會(huì)報(bào)錯(cuò)。只是你如果這么寫的話編譯器不會(huì)給你調(diào)用子類的實(shí)現(xiàn),而是還是調(diào)用基類的實(shí)現(xiàn)。
7.在析構(gòu)函數(shù)中也不要調(diào)用虛函數(shù)。在析構(gòu)的時(shí)候會(huì)首先調(diào)用子類的析構(gòu)函數(shù),析構(gòu)掉對(duì)象中的子類部分,然后在調(diào)用基類的析構(gòu)函數(shù)析構(gòu)基類部分,如果在基類的析構(gòu)函數(shù)里面調(diào)用虛函數(shù),會(huì)導(dǎo)致其調(diào)用已經(jīng)析構(gòu)了的子類對(duì)象里面的函數(shù),這是非常危險(xiǎn)的。
8. 記得在寫派生類的拷貝函數(shù)時(shí),調(diào)用基類的拷貝函數(shù)拷貝基類的部分。

總結(jié):

1、 派生類重寫基類的虛函數(shù)實(shí)現(xiàn)多態(tài), 要求函數(shù)名 、 參數(shù)列表、 返回值完全相同。 (協(xié)變除外)。

2、 基類中定義了 虛函數(shù), 在派生類中該函數(shù)始終保持虛函數(shù)的特性。

3、 只 有類的非靜態(tài)成員 函數(shù)才能定義為虛函數(shù), 靜態(tài)成員 函數(shù)不能定義為虛函數(shù)。

4、 如果在類外定義虛函數(shù), 只 能在聲明函數(shù)時(shí)加virtual關(guān)鍵字, 定義時(shí)不用加。

5、 構(gòu)造函數(shù)不能定義為虛函數(shù), 雖然可以將operator=定義為虛函數(shù), 但最好不要這么做, 使用時(shí)容易混淆。

6、 不要在構(gòu)造函數(shù)和析構(gòu)函數(shù)中調(diào)用虛函數(shù), 在構(gòu)造函數(shù)和析構(gòu)函數(shù)中, 對(duì)象是不完整的, 可能會(huì)出現(xiàn)未定義的行為。

7、 最好將基類的析構(gòu)函數(shù)聲明為虛函數(shù)。 ( 因?yàn)榕缮惖奈鰳?gòu)函數(shù)跟基類的析構(gòu)函數(shù)名稱不一樣, 但是構(gòu)成覆蓋, 這里編譯器做了特殊處理)

8、 虛表是所有類對(duì)象實(shí)例共用的。

關(guān)于靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。


分享名稱:靜態(tài)多態(tài)與動(dòng)態(tài)多態(tài)以及虛函數(shù)之間的關(guān)聯(lián)是什么
文章出自:http://weahome.cn/article/psgisj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部