常見為公有派生:
class RatedPlayer : public TableTennisPlayer
{..}
冒號表明,RatedPlayer的基類是TableTennisPlayer。使用公有派生,基類的公有部分將稱為派生類的公有部分,基類的私有部分將稱為派生類的一部分,但不能被派生類直接訪問,只能通過基類的公有和保護方法訪問。派生類需要自己的構(gòu)造函數(shù),并根據(jù)需要添加額外的數(shù)據(jù)成員和成員函數(shù)。
創(chuàng)建派生類對象時,首先調(diào)用基類構(gòu)造函數(shù),然后再調(diào)用派生類的構(gòu)造函數(shù)。基類構(gòu)造函數(shù)負責初始化繼承的數(shù)據(jù)成員,派生類構(gòu)造函數(shù)主要用于初始化新增的數(shù)據(jù)成員。派生類的構(gòu)造函數(shù)總是調(diào)用一個基類的構(gòu)造函數(shù)。可以使用初始化列表語法指明要使用的基類構(gòu)造函數(shù),否則將使用默認的基類構(gòu)造函數(shù)。
派生類對象過期時,先調(diào)用派生類的析構(gòu)函數(shù),再調(diào)用基類析構(gòu)函數(shù)。
使用派生類程序必須能夠訪問到基類。由于兩個類是相關(guān)的,一般將他們的聲明放在同一個.h文件中。
基類指針可以在不進行顯式類型轉(zhuǎn)換的情況下指向派生類對象;基類引用可以在不進行顯式類型轉(zhuǎn)換的情況下引用派生類對象,但不能反過來,即不能將基類對象和地址賦給派生類引用或指針。基類指針或引用只能用于調(diào)用基類方法(聲明了虛方法后,可以用于調(diào)用同名覆蓋的派生類方法)。
公有繼承是一種is-a關(guān)系。
虛函數(shù)——多態(tài)重要機制:在方法聲明前加上virtual關(guān)鍵字,聲明為虛方法,則它在派生類中將自動成為虛方法。然而在派生類中最好也加上virtual聲明指出來,看著方便。virtual只用于類聲明的方法原型中,定義中不需要。
如果沒有使用虛方法,在調(diào)用同名的方法時,程序?qū)⒏鶕?jù)引用類型或指針類型選擇方法;如果使用了虛方法,程序?qū)⒏鶕?jù)引用或指針指向的對象的類型來選擇方法。
通常,基類需要聲明虛析構(gòu)函數(shù)。如果析構(gòu)函數(shù)不是虛的,則將只調(diào)用對應于指針類型的析構(gòu)函數(shù),即使其指向的是派生類對象。因此為確保正確釋放派生對象時,按正確的順序調(diào)用析構(gòu)函數(shù),需要聲明虛析構(gòu)函數(shù)。
編譯器對非虛方法使用靜態(tài)聯(lián)編,即在編譯時就能確定使用的是哪一個函數(shù);對虛方法使用動態(tài)聯(lián)編,即在程序運行時選擇使用哪一個函數(shù)。為避免額外的處理開銷,默認為靜態(tài)聯(lián)編。所謂的開銷是指在內(nèi)存和執(zhí)行速度方面有一定的成本:
1、每個對象都將增大,增大量為存儲地址的空間;
2、對于每個類,編譯器都創(chuàng)建一個虛函數(shù)地址表(數(shù)組);
3、對于每個函數(shù)調(diào)用,都需要執(zhí)行一項額外的操作,即到表中查找地址。
虛函數(shù)表中存儲了為類對象進行聲明的虛函數(shù)的地址。例如,基類對象包含一個指針(形如隱藏的成員),指向基類中所有虛函數(shù)的地址表。派生類對象將包含一個指向獨立地址表的指針。如果派生類提供了虛函數(shù)的新定義,該表將保存新函數(shù)的地址;如果沒有重新定義虛函數(shù),該表將保存函數(shù)原始版本的地址。如果派生類定義了新的虛函數(shù),則該函數(shù)的地址也被添加到該表中。
構(gòu)造函數(shù)不能是虛函數(shù)。創(chuàng)建派生類對象時,將調(diào)用派生類的構(gòu)造函數(shù),然后其將使用基類的一個構(gòu)造函數(shù),這種順序不同于繼承機制。因此,派生類并不繼承基類的構(gòu)造函數(shù)。
析構(gòu)函數(shù)應當是虛函數(shù),即使它不執(zhí)行任何操作,除非類不用做基類。
友元不能是虛函數(shù),因為友元不是類成員,只有成員函數(shù)才能是虛函數(shù)。
如果派生類沒有重新定義函數(shù),將使用該函數(shù)的基類版本。如果派生類位于派生鏈中,則將使用最新的虛函數(shù)版本,例外情況是基類版本是隱藏的(被覆蓋)。
如果派生類有重新定義函數(shù),不會生成函數(shù)的兩個重載版本,而是隱藏了基類版本。將不是使用相同的函數(shù)特征標覆蓋基類聲明,而是隱藏同名的基類方法,不管參數(shù)特征標如何。
PRotect成員表示,派生類的成員可以直接訪問基類的保護成員,但不能訪問基類的私有成員。即,對于外部世界來說,保護成員的行為與私有成員類似;而對于派生類來說,保護成員的行為與公有成員相似。
抽象基類:
通過純虛函數(shù)提供未實現(xiàn)的函數(shù)。純虛函數(shù)的聲明前面為virtual關(guān)鍵字,結(jié)尾處為 = 0(如果有const,則結(jié)尾為const = 0)。當類聲明包含純虛函數(shù)時,則不能創(chuàng)建該類的對象。這里的理念是,包含純虛函數(shù)的類只能用作基類,即抽象基類。抽象基類至少包含一個純虛函數(shù)。在類中允許不定義純虛函數(shù)。
如果在派生類中仍沒有實現(xiàn)純虛函數(shù)定義,則仍為抽象類,不能實例化。
抽象基類(或叫ABC)看作是一種必須實施的接口。ABC要求具體派生類覆蓋其純虛函數(shù)——迫使派生類遵循ABC設(shè)置的接口規(guī)則,即接口約定。這樣確保了從ABC派生的所有組件都至少支持ABC指定的功能。
繼承和動態(tài)內(nèi)存分配的問題:假設(shè)基類成員包含指針,構(gòu)造函數(shù)使用了動態(tài)內(nèi)存分配(即new),且聲明中包含了構(gòu)造函數(shù)使用new時需要的特殊方法:析構(gòu)函數(shù)、復制構(gòu)造函數(shù)和重載賦值運算符。如果派生類不使用new,則不再需要為派生類定義顯式析構(gòu)函數(shù)、復制構(gòu)造函數(shù)和賦值運算符。反之,如果派生類使用了new,則必須為派生類定義顯式析構(gòu)函數(shù)、復制構(gòu)造函數(shù)和賦值運算符。
新聞熱點
疑難解答