- 相關(guān)推薦
2016計算機二級考試輔導(dǎo):C++多態(tài)性基本概念講述
前幾天筆試的時候碰到考C++多態(tài)性的題目,因為不是自己的專業(yè)不是純做軟件開發(fā),C++學習不是很好,做得有點混亂;貋硪院罅⒖滩榱讼嚓P(guān)資料,大概明白了一點,可能以后解題的時候不會亂了。
先摘下一些網(wǎng)上的書上的基本概念。
多態(tài)性可以簡單地概括為“一個接口,多種方法”,程序在運行時才決定調(diào)用的函數(shù),它是面向?qū)ο缶幊填I(lǐng)域的核心概念。多態(tài)(polymorphisn),字面意思多種形狀。
C++多態(tài)性是通過虛函數(shù)來實現(xiàn)的,虛函數(shù)允許子類重新定義成員函數(shù),而子類重新定義父類的做法稱為覆蓋(override),或者稱為重寫。(這里我覺得要補充,重寫的話可以有兩種,直接重寫成員函數(shù)和重寫虛函數(shù),只有重寫了虛函數(shù)的才能算作是體現(xiàn)了C++多態(tài)性)而重載則是允許有多個同名的函數(shù),而這些函數(shù)的參數(shù)列表不同,允許參數(shù)個數(shù)不同,參數(shù)類型不同,或者兩者都不同。編譯器會根據(jù)這些函數(shù)的不同列表,將同名的函數(shù)的名稱做修飾,從而生成一些不同名稱的預(yù)處理函數(shù),來實現(xiàn)同名函數(shù)調(diào)用時的重載問題。但這并沒有體現(xiàn)多態(tài)性。
多態(tài)與非多態(tài)的實質(zhì)區(qū)別就是函數(shù)地址是早綁定還是晚綁定。如果函數(shù)的調(diào)用,在編譯器編譯期間就可以確定函數(shù)的調(diào)用地址,并生產(chǎn)代碼,是靜態(tài)的,就是說地址是早綁定的。而如果函數(shù)調(diào)用的地址不能在編譯器期間確定,需要在運行時才確定,這就屬于晚綁定。
那么多態(tài)的作用是什么呢,封裝可以使得代碼模塊化,繼承可以擴展已存在的代碼,他們的目的都是為了代碼重用。而多態(tài)的目的則是為了接口重用。也就是說,不論傳遞過來的究竟是那個類的對象,函數(shù)都能夠通過同一個接口調(diào)用到適應(yīng)各自對象的實現(xiàn)方法。
最常見的用法就是聲明基類的指針,利用該指針指向任意一個子類對象,調(diào)用相應(yīng)的虛函數(shù),可以根據(jù)指向的子類的不同而實現(xiàn)不同的方法。如果沒有使用虛函數(shù)的話,即沒有利用C++多態(tài)性,則利用基類指針調(diào)用相應(yīng)的函數(shù)的時候,將總被限制在基類函數(shù)本身,而無法調(diào)用到子類中被重寫過的函數(shù)。因為沒有多態(tài)性,函數(shù)調(diào)用的地址將是一定的,而固定的地址將始終調(diào)用到同一個函數(shù),這就無法實現(xiàn)一個接口,多種方法的目的了。
筆試的題目
#include class A { public: void foo() { printf("1"); } virtual void fuu() { printf("2"); } }; class B:public A { public: void foo() { printf("3"); } void fuu() { printf("4"); } }; int main() { A a; B b; A *p = &a; p->foo(); p->fuu(); p = &b; p->foo(); p->fuu(); return 0; } 第一個p->foo()和p->fuu()都很好理解,本身是基類指針,指向的又是基類對象,調(diào)用的都是基類本身的函數(shù),因此輸出結(jié)果就是 1、2。
第二個p->foo()和p->fuu()則是基類指針指向子類對象,正式體現(xiàn)多態(tài)的用法,p->foo()由于指針是個基類指針,指向是一個固定偏移量的函數(shù),因此此時指向的就只能是基類的foo()函數(shù)的代碼了,因此輸出的結(jié)果還是1。而p->fuu()指針是基類指針,指向的fuu是一個虛函數(shù),由于每個虛函數(shù)都有一個虛函數(shù)列表,此時p調(diào)用fuu()并不是直接調(diào)用函數(shù),而是通過虛函數(shù)列表找到相應(yīng)的函數(shù)的地址,因此根據(jù)指向的對象不同,函數(shù)地址也將不同,這里將找到對應(yīng)的子類的fuu()函數(shù)的地址,因此輸出的結(jié)果也會是子類的結(jié)果4.
筆試的題目中還有一個另類測試方法。即
B *ptr = (B *)&a; ptr->foo(); ptr->fuu();
問這兩調(diào)用的輸出結(jié)果。這是一個用子類的指針去指向一個強制轉(zhuǎn)換為子類地址的基類對象。結(jié)果,這兩句調(diào)用的輸出結(jié)果是3,2。
并不是很理解這種用法,從原理上來解釋,由于B是子類指針,雖然被賦予了基類對象地址,但是ptr->foo()在調(diào)用的時候,由于地址偏移量固定,偏移量是子類對象的偏移量,于是即使在指向了一個基類對象的情況下,還是調(diào)用到了子類的函數(shù),雖然可能從始到終都沒有子類對象的實例化出現(xiàn)。
而ptr->fuu()的調(diào)用,可能還是因為C++多態(tài)性的原因,由于指向的是一個基類對象,通過虛函數(shù)列表的引用,找到了基類中foo ()函數(shù)的地址,因此調(diào)用了基類的函數(shù)。由此可見多態(tài)性的強大,可以適應(yīng)各種變化,不論指針是基類的還是子類的,都能找到正確的實現(xiàn)方法。
【計算機二級考試輔導(dǎo):C++多態(tài)性基本概念講述】相關(guān)文章:
計算機二級考試C++練習及答案10-09
計算機二級考試C++試題及答案09-15
計算機二級考試C++考前沖刺試題10-13
計算機二級C++考試試題及答案10-29
計算機二級考試C++上機考試試題05-22
計算機二級C++考點:C++語言概述07-17
計算機二級C++上機考試試題06-16