封裝(encapsulation):就是將抽象得到的數(shù)據(jù)和行為(或功能)相結(jié)合,形成一個有機的整體,也就是將數(shù)據(jù)與操作數(shù)據(jù)的源代碼進行有機的結(jié)合,形成”類”,其中數(shù)據(jù)和函數(shù)都是類的成員。封裝的目的是增強安全性和簡化編程,使用者不必了解具體的實現(xiàn)細節(jié),而只是要通過外部接口,特定的訪問權(quán)限來使用類的成員。封裝可以隱藏實現(xiàn)細節(jié),使得代碼模塊化。
繼承(inheritance):C++通過類派生機制來支持繼承。被繼承的類型稱為基類或超類,新產(chǎn)生的類為派生類或子類。保持已有類的特性而構(gòu)造新類的過程稱為繼承。在已有類的基礎上新增自己的特性而產(chǎn)生新類的過程稱為派生。繼承和派生的目的是保持已有類的特性并構(gòu)造新類。繼承的目的:實現(xiàn)代碼重用。派生的目的:實現(xiàn)代碼擴充。三種繼承方式:public、protected、private。
繼承時的構(gòu)造函數(shù):(1)、基類的構(gòu)造函數(shù)不能被繼承,派生類中需要聲明自己的構(gòu)造函數(shù);(2)、聲明構(gòu)造函數(shù)時,只需要對本類中新增成員進行初始化,對繼承來的基類成員的初始化,自動調(diào)用基類構(gòu)造函數(shù)完成;(3)、派生類的構(gòu)造函數(shù)需要給基類的構(gòu)造函數(shù)傳遞參數(shù);(4)、單一繼承時的構(gòu)造函數(shù):派生類名::派生類名(基類所需的形參,本類成員所需的形參):基類名(參數(shù)表) {本類成員初始化賦值語句;};(5)、當基類中聲明有默認形式的構(gòu)造函數(shù)或未聲明構(gòu)造函數(shù)時,派生類構(gòu)造函數(shù)可以不向基類構(gòu)造函數(shù)傳遞參數(shù);(6)、若基類中未聲明構(gòu)造函數(shù),派生類中也可以不聲明,全采用缺省形式構(gòu)造函數(shù);(7)、當基類聲明有帶形參的構(gòu)造函數(shù)時,派生類也應聲明帶形參的構(gòu)造函數(shù),并將參數(shù)傳遞給基類構(gòu)造函數(shù);(8)、構(gòu)造函數(shù)的調(diào)用次序:A、調(diào)用基類構(gòu)造函數(shù),調(diào)用順序按照它們被繼承時聲明的順序(從左向右);B、調(diào)用成員對象的構(gòu)造函數(shù),調(diào)用順序按照它們在類中的聲明的順序;C、派生類的構(gòu)造函數(shù)體中的內(nèi)容。
繼承時的析構(gòu)函數(shù):(1)、析構(gòu)函數(shù)也不被繼承,派生類自行聲明;(2)、聲明方法與一般(無繼承關(guān)系時)類的析構(gòu)函數(shù)相同;(3)、不需要顯示地調(diào)用基類的析構(gòu)函數(shù),系統(tǒng)會自動隱式調(diào)用;(4)、析構(gòu)函數(shù)的調(diào)用次序與構(gòu)造函數(shù)相反。
同名隱藏規(guī)則:當派生類與基類中有相同成員時:(1)、若未強行指名,則通過派生類對象使用的是派生類中的同名成員;(2)、如要通過派生類對象訪問基類中被覆蓋的同名成員,應使用基類名限定:基類名::數(shù)據(jù)成員名。
虛基類:作用:(1)、主要用來解決多繼承時可能發(fā)生的對同一基類繼承多次而產(chǎn)生的二義性問題;(2)、為最遠的派生類提供唯一的基類成員,而不重復產(chǎn)生多次拷貝。
繼承、組合:組合是將其它類的對象作為成員使用,繼承是子類可以使用父類的成員方法。(1)、A繼承B,說明A是B的一種,并且B的所有行為對A都有意義;(2)、若在邏輯上A是B的“一部分”,則不允許B從A派生,而是要用A和其它東西組合出B;(3)、繼承屬于”白盒”復用,組合屬于”黑盒”復用。
多態(tài)(Polymorphic)性可以簡單地概括為“一個接口,多種方法”,程序在運行時才決定調(diào)用的函數(shù)。C++多態(tài)性是通過虛函數(shù)來實現(xiàn)的,虛函數(shù)允許子類重新定義成員函數(shù),而子類重新定義父類的做法稱為覆蓋或者稱為重寫。而重載則是允許有多個同名的函數(shù),而這些函數(shù)的參數(shù)列表不同,允許參數(shù)個數(shù)不同,參數(shù)類型不同,或者兩者都不同。關(guān)于多態(tài),簡而言之就是用父類型別的指針指向其子類的實例,然后通過父類的指針調(diào)用實際子類的成員函數(shù)。
多態(tài)與非多態(tài)的實質(zhì)區(qū)別就是函數(shù)地址是早綁定還是晚綁定。如果函數(shù)的調(diào)用,在編譯器編譯期間就可以確定函數(shù)的調(diào)用地址,并產(chǎn)生代碼,是靜態(tài)的,就是說地址是早綁定的。而如果函數(shù)調(diào)用的地址不能在編譯期間確定,需要在運行時才確定,這就是屬于晚綁定。
封裝可以使得代碼模塊化,繼承可以擴展已存在的代碼,它們的目的都是為了代碼重用。而多態(tài)的目的則是為了接口重用。也就是說不論傳遞過來的究竟是哪個類的對象,函數(shù)都能夠通過同一個接口調(diào)用到適應各自對象的實現(xiàn)方法。
最常見的用法就是聲明基類的指針,利用該指針指向任意一個子類對象,調(diào)用相應的虛函數(shù),可以根據(jù)指向的子類的不同而實現(xiàn)不同的方法。如果沒有使用虛函數(shù)的話,即沒有利用C++多態(tài)性,則利用基類指針調(diào)用相應的函數(shù)的時候,將總被限制在基類函數(shù)本身,而無法調(diào)用到子類中被重寫過的函數(shù)。因為沒有多態(tài)性,函數(shù)調(diào)用的地址將是一定的,而固定的地址將始終調(diào)用到同一個函數(shù),這就無法實現(xiàn)一個接口,多種方法的目的了。
純虛函數(shù)是在基類中聲明的虛函數(shù),它在基類中沒有定義,但要求任何派生類都要定義自己的實現(xiàn)方法。在基類中實現(xiàn)純虛函數(shù)的方法是在函數(shù)原型后加“= 0”。為了方便使用多態(tài)特性,常常需要在基類中定義虛函數(shù),在很多情況下,基類本身生成對象是不合情理的。為了解決這些問題,引入了純虛函數(shù)的概念,將函數(shù)定義為純虛函數(shù),則編譯器要求在派生類中必須予以重寫以實現(xiàn)多態(tài)性。同時含有純虛函數(shù)的類稱為抽象類,它不能生成對象。由于純虛函數(shù)所在的類中沒有它的定義,在該類的構(gòu)造函數(shù)和析構(gòu)函數(shù)中不允許調(diào)用純虛函數(shù),否則會導致程序運行錯誤,但其它成員函數(shù)可以調(diào)用純虛函數(shù)。
C++支持兩種多態(tài)性:(1)、編譯時多態(tài)性(靜態(tài)多態(tài),在編譯時就可以確定對象使用的形式):通過重載函數(shù)實現(xiàn);(2)、運行時多態(tài)性(動態(tài)多態(tài),其具體引用的對象在運行時才能確定):通過虛函數(shù)實現(xiàn)。
C++中,實現(xiàn)多態(tài)有以下方法:虛函數(shù)、抽象類、重載、覆蓋、模板。
函數(shù)重載(Overload):指在相同作用域里(如同一類中),函數(shù)同名不同參,返回值則不用理會,不同參可以是不同個數(shù),也可以是不同類型。效果:根據(jù)實參的個數(shù)和類型調(diào)用對應的函數(shù)體。
函數(shù)覆蓋(Override)(函數(shù)重寫):指派生類中的函數(shù)覆蓋基類中的同名同參虛函數(shù),因此作用域不同。效果:基類指針或引用訪問虛函數(shù)時會根據(jù)實例的類型調(diào)用對應的函數(shù)。
函數(shù)隱藏(Hide):對于子類中與基類同名的函數(shù),如果不是覆蓋那就成了隱藏。兩種情況:(1)、同名不同參;(2)、同名同參但基類不是virtual函數(shù)。
派生類的構(gòu)造函數(shù)使用說明:(1)、在派生類構(gòu)造函數(shù)中,只要基類不是僅使用無參的默認構(gòu)造函數(shù),都要顯示的給出基類名稱參數(shù)表;(2)、基類沒有定義構(gòu)造函數(shù),派生類也可以不定義,使用默認構(gòu)造函數(shù);(3)、基類有帶參構(gòu)造函數(shù),派生類必須定義構(gòu)造函數(shù)。
虛函數(shù)的重載函數(shù)仍是虛函數(shù)。在派生類重定義虛函數(shù)時必須有相同的函數(shù)原型,包括返回類型、函數(shù)名、參數(shù)個數(shù)、參數(shù)類型的順序必須相同。虛函數(shù)必須是類的成員函數(shù),不能為全局函數(shù),也不能為靜態(tài)函數(shù)。不能將友員說明為虛函數(shù),但虛函數(shù)可以是另一個類的友員。析構(gòu)函數(shù)可以是虛函數(shù),但構(gòu)造函數(shù)不能為虛函數(shù)。一般地講,若某類中定義有虛函數(shù),則其析構(gòu)函數(shù)也應當說明為虛函數(shù)。特別是在析構(gòu)函數(shù)需要完成一些有意義的操作,比如釋放內(nèi)存時,尤其應當如此。在類系統(tǒng)中訪問一個虛函數(shù)時,應使用指向基類類型的指針或?qū)愵愋偷囊茫詽M足運行時多態(tài)性的要求。當然也可以像調(diào)用普通成員函數(shù)那樣利用對象名來調(diào)用一個函數(shù)。若在派生類中沒有重新定義虛函數(shù),則該類的對象將使用其基類中的虛函數(shù)代碼。
抽象類:如果一個類中至少有一個純虛函數(shù),那么這個類被稱為抽象類。抽象類不僅包括純虛函數(shù),也可包括虛函數(shù)。抽象類中的純虛函數(shù)可能是在抽象類中定義的,也可能是從它的抽象基類中繼承下來且重定義的。抽象類有一個重要特點,即抽象類必須用作派生其它類的基類,而不能用于直接創(chuàng)建對象實例。抽象類不能直接創(chuàng)建對象的原因是其中有一個或多個函數(shù)沒有定義,但仍可使用指向抽象類的指針支持運行時多態(tài)性。派生類中必須重載基類中的純虛函數(shù),否則它仍將被看作一個抽象類。從基類繼承來的純虛函數(shù),在派生類中仍是虛函數(shù)。
虛函數(shù)表:虛函數(shù)是通過一張?zhí)摵瘮?shù)表來實現(xiàn)的。簡稱為V-Table,在這個表中,主要是一個類的虛函數(shù)的地址表,這張表解決了繼承、覆蓋的問題,保證其真實反應實際的函數(shù)。這樣,在有虛函數(shù)的類的實例中這個表被分配在了這個實例的內(nèi)存中,所以,當我們用父類的指針來操作一個子類的時候,這張?zhí)摵瘮?shù)表就顯得有無重要了,它就像一個地圖一樣,指明了實際所應該調(diào)用的函數(shù)。
一個多態(tài)的例子:
#include <iostream> using namespace std; class A { public: void foo() { printf("1\n"); } virtual void fun() { printf("2\n"); } }; class B : public A { public: void foo() { printf("3\n"); } void fun() { printf("4\n"); } }; int main(void) { A a; B b; A* p = &a; p->foo();//1 p->fun();//2 p = &b; p->foo();//1 p->fun();//4 B* ptr = (B*)&a; ptr->foo();//3 ptr->fun();//2 return 0; }
另外有需要云服務器可以了解下創(chuàng)新互聯(lián)建站chinadenli.net,海內(nèi)外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。
名稱欄目:C++中的封裝、繼承、多態(tài)理解-創(chuàng)新互聯(lián)
網(wǎng)頁地址:http://chinadenli.net/article28/iosjp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設計公司、品牌網(wǎng)站建設、網(wǎng)站設計公司、外貿(mào)建站、關(guān)鍵詞優(yōu)化、微信公眾號
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容