




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、C+程序設(shè)計(jì)程序設(shè)計(jì)第6章 類的繼承 第第6 6章章 類的繼承類的繼承 繼承(Inheritance)是C+語(yǔ)言的重要機(jī)制,是面向?qū)ο蟪绦蛟O(shè)計(jì)方法的三個(gè)基本特征之一。繼承允許程序在已有類的基礎(chǔ)上進(jìn)行擴(kuò)展,是一種重要的代碼復(fù)用手段。繼承反映了類與類之間的一種層次關(guān)系,更是現(xiàn)實(shí)世界中事物之間存在的復(fù)雜聯(lián)系的體現(xiàn)。繼承也體現(xiàn)了人類認(rèn)識(shí)事物由簡(jiǎn)單到復(fù)雜的過(guò)程和思考問(wèn)題的方法。 本章著重學(xué)習(xí)繼承這一面向?qū)ο蟪绦蛟O(shè)計(jì)的重要概念,以及在C+語(yǔ)言中實(shí)現(xiàn)繼承的相關(guān)技術(shù)。6.1 6.1 面向?qū)ο缶幊堂嫦驅(qū)ο缶幊汤^承繼承 6.26.2 派生類派生類 6.3 6.3 派生類的構(gòu)造與析構(gòu)派生類的構(gòu)造與析構(gòu)6.4 6.4
2、 多重繼承與虛基類多重繼承與虛基類 6.56.5 案例實(shí)訓(xùn)案例實(shí)訓(xùn) 第第6 6章章 類的繼承類的繼承6.1 6.1 面向?qū)ο缶幊堂嫦驅(qū)ο缶幊汤^承繼承 類的繼承機(jī)制是指類可以在已定義類的基礎(chǔ)上派生出新類,新類將擁有原有類的數(shù)據(jù)和函數(shù),并且可以增添新的數(shù)據(jù)和函數(shù)成員,或者對(duì)原有類中的成員進(jìn)行更新。 在面向?qū)ο缶幊讨?,原有類被稱為基類在面向?qū)ο缶幊讨?,原有類被稱為基類(Base (Base Class)Class)或父類或父類(Super Class)(Super Class),新產(chǎn)生的類被稱為派生,新產(chǎn)生的類被稱為派生類類(Derived Class)(Derived Class)或子類或子類(S
3、ub Class)(Sub Class)。 例如,由學(xué)生類可以派生出中學(xué)生類、大學(xué)生類和研究生類。由交通工具類可派生出汽車類、輪船類和飛機(jī)類,而汽車類又可充當(dāng)客車類和卡車類的基類。 類的繼承有兩種方式:?jiǎn)卫^承和多重繼承。類的繼承有兩種方式:?jiǎn)卫^承和多重繼承。單繼承的派生類有且僅有一個(gè)直接基類,如圖6-1中的飛機(jī)類是單繼承于交通工具類,戰(zhàn)斗機(jī)類則是單繼承于飛機(jī)類。在單繼承中,可以視派生類是基類的特例。 多重繼承的派生類具有兩個(gè)或兩個(gè)以上的直接基類,如圖6-1中的水陸兩用車類繼承于客車類和客船類。在多重繼承中,派生類是從多個(gè)基類派生而來(lái),是一個(gè)具有多個(gè)基類特征的復(fù)合體,就像雜交水稻具有不同稻種特性
4、一樣。6.1 6.1 面向?qū)ο缶幊堂嫦驅(qū)ο缶幊汤^承繼承6.1 6.1 面向?qū)ο缶幊堂嫦驅(qū)ο缶幊汤^承繼承圖6-1 類的單繼承和多重繼承 6.1 6.1 面向?qū)ο缶幊堂嫦驅(qū)ο缶幊汤^承繼承 繼承與組合都屬于面向?qū)ο蟮拇a復(fù)用技術(shù)。繼承和組合既有區(qū)別,也有聯(lián)系。在一些復(fù)雜的類的設(shè)計(jì)中,二者經(jīng)常是一起使用。在某些情況下,繼承和組合的實(shí)現(xiàn)方法還可以互換。例如,圓(Circle)類的設(shè)計(jì),其圓心用點(diǎn)(Point)類來(lái)描述,此時(shí),即可以以Point類為父類設(shè)計(jì)Circle類,使其擁有圓心坐標(biāo),也可以在Circle類中用Point類定義數(shù)據(jù)成員center。代碼框架如下:class Point /點(diǎn)類priva
5、te:double x, y;public:.;class Circle /組合private:double radius;double radius;public:.;class Circle : public Point /繼承private:Point center;public:.6.1 6.1 面向?qū)ο缶幊堂嫦驅(qū)ο缶幊汤^承繼承6.2 6.2 派生類派生類 派生類繼承了基類的數(shù)據(jù)成員和函數(shù)成員。C+支持3種繼承方式,不同的繼承方式?jīng)Q定了基類中成員被派生類繼承后的可見(jiàn)性。派生類中可以重定義基類中的同名成員函數(shù)。派生類與基類屬于同一類族,它們之間存在賦值兼容問(wèn)題。 本節(jié)主要介紹派生類的定義
6、、繼承方式、成員函數(shù)覆蓋和賦值兼容等基礎(chǔ)知識(shí)。6.2 6.2 派生類派生類6.2.1 派生類的定義定義派生類的一般格式如下:定義派生類的一般格式如下:class : , ., ;其中:l 與類的定義相似,用關(guān)鍵字class標(biāo)明是類定義。區(qū)別在于派生類名后(用冒號(hào)分隔)列出所繼承的基類。對(duì)于單繼承只有一個(gè)基類,而多重繼承則有多個(gè)基類,它們之間用逗號(hào)分隔。l 繼承方式有3種:公有繼承(public)、私有繼承(private)和保護(hù)繼承(protected)。不指明繼承方式等同于私有繼承。l 派生類中的成員包括數(shù)據(jù)成員和成員函數(shù)。與普通類相同,派生類中數(shù)據(jù)成員的訪問(wèn)控制限定通常是私有的,成員函數(shù)是
7、公有的。6.2 6.2 派生類派生類【例6-1】派生類定義與派生類對(duì)象中的數(shù)據(jù)成員和成員函數(shù)。 6.2 6.2 派生類派生類跟蹤與觀察:(1)從前面的知識(shí)可知,對(duì)象在邏輯上數(shù)據(jù)成員與函數(shù)成員具有封裝性,但在物理上其實(shí)是存儲(chǔ)在內(nèi)存的不同區(qū)域(堆棧區(qū)和代碼區(qū))。 從圖6-2(a)可見(jiàn),派生類對(duì)象derivedObj的數(shù)據(jù)部分含有兩部分?jǐn)?shù)據(jù)BaseClass和derivedData(其值為600),展開(kāi)BaseClass項(xiàng),其中含有baseData(其值為500)。 對(duì)象derivedObj自動(dòng)包含了基類部分,并且派生類的構(gòu)造函數(shù)通過(guò)調(diào)用基類的構(gòu)造函數(shù)將500賦給了baseData。(2)從圖6-2
8、(b)可見(jiàn),派生類對(duì)象derivedObj繼承了基類的公有函數(shù)show,DerivedClass:show的值是0 x010a14b0 BaseClass:show(void),與BaseClass:show完全相同。 6.2 6.2 派生類派生類 ( b)圖6-2 派生類對(duì)象擁有的數(shù)據(jù)成員和成員函數(shù) 派生類繼承基類的成員函數(shù)也是自動(dòng)的,系統(tǒng)自動(dòng)將基類的成員函數(shù)show當(dāng)成派生類的成員函數(shù)show,但實(shí)際上兩者都是同一個(gè)函數(shù)void BaseClass:show(void)。6.2 6.2 派生類派生類 C+中下列特殊的成員函數(shù)不被派生類所繼承: 構(gòu)造函數(shù);析構(gòu)函數(shù);私有函數(shù);賦值運(yùn)算符(=)
9、重載函數(shù)。 構(gòu)造函數(shù)、析構(gòu)函數(shù)和賦值運(yùn)算符重載函數(shù)不被繼承的主要原因是基類的對(duì)應(yīng)函數(shù)不能處理在派生類引入的新的數(shù)據(jù)成員,不能完全正確地完成相應(yīng)的功能(只能正確地處理基類的數(shù)據(jù)成員)。因而,派生類對(duì)象在調(diào)用這些函數(shù)時(shí)會(huì)首先調(diào)用基類的對(duì)應(yīng)函數(shù)。6.2 6.2 派生類派生類在派生類設(shè)計(jì)時(shí),需要注意下面幾點(diǎn):l 派生類吸收基類成員。派生類繼承吸收了基類的全部數(shù)據(jù)成員以及除了構(gòu)造函數(shù)、析構(gòu)函數(shù)、賦值和私有函數(shù)之外的全部函數(shù)成員。l 派生類修改基類成員。對(duì)繼承到派生類中基類成員的修改包括兩個(gè)方面:一是基類成員的訪問(wèn)方式問(wèn)題,這由派生類定義時(shí)的繼承方式來(lái)控制;二是對(duì)基類成員的覆蓋,也就是在派生類中定義了與基
10、類中同名的數(shù)據(jù)成員或成員函數(shù),由于作用域不同,于是發(fā)生同名覆蓋(Override),基類中的成員就被替換成派生類中的同名成員。l 派生類增添新成員。在派生類中,除了從基類中繼承過(guò)來(lái)的成員外,還可以根據(jù)需要在派生類中添加新的數(shù)據(jù)成員和成員函數(shù),以此實(shí)現(xiàn)必要的新功能。在派生類中添加新成員是繼承和派生機(jī)制的核心,它保證了派生類是基類的擴(kuò)展。6.2 6.2 派生類派生類6.2.2 繼承方式與訪問(wèn)控制l 在類的定義中,用訪問(wèn)控制符private、protected和public說(shuō)明成員的可見(jiàn)性。公有成員能被任何函數(shù)所訪問(wèn),而私有和保護(hù)成員僅能接受類的成員函數(shù)和類的友元(包括友元函數(shù)和友元類)的訪問(wèn)。派生
11、類繼承于基類,那么基類成員對(duì)派生類函數(shù)的可見(jiàn)性如何呢?l 派生類在定義時(shí)需要指定繼承方式,所使用的關(guān)鍵字也是private、protected和public,它們分別對(duì)應(yīng)私有繼承、保護(hù)繼承和公有繼承3種方式。不同的繼承方式?jīng)Q定了基類中的成員在派生類中的可見(jiàn)性,表6-1列出了3種繼承方式在派生類中影響基類成員的可見(jiàn)性和訪問(wèn)控制屬性的情況。6.2 6.2 派生類派生類表6-1 派生類對(duì)基類成員的訪問(wèn)能力 基類成員繼承方式privateprotectedpublicprivate不可訪問(wèn)可訪問(wèn)/私有成員可訪問(wèn)/私有成員protected不可訪問(wèn)可訪問(wèn)/保護(hù)成員可訪問(wèn)/保護(hù)成員public不可訪問(wèn)可訪
12、問(wèn)/保護(hù)成員可訪問(wèn)/公有成員6.2 6.2 派生類派生類l 表6-1中的“不可訪問(wèn)”和“可訪問(wèn)”表示在派生類中訪問(wèn)基類成員的能力?!八接谐蓡T”、“保護(hù)成員”和“公有成員”表示基類成員在派生類中訪問(wèn)控制屬性變化情況。l 例如,基類是public的成員采用private繼承方式時(shí),表中相應(yīng)項(xiàng)為“可訪問(wèn)/私有成員”,表示在派生類中可直接訪問(wèn)基類的公有成員,但該成員在派生類中其訪問(wèn)控制屬性已被改為是私有成員,因此從派生類對(duì)象外不可直接訪問(wèn)基類的公有成員(從基類對(duì)象外可以直接訪問(wèn))。派生類中基類成員訪問(wèn)控制屬性的改變直接影響到基類成員在派生類對(duì)象外的訪問(wèn)能力。6.2 6.2 派生類派生類從縱向觀察表6-
13、1可知:l 基類的私有成員無(wú)論采用怎樣的繼承方式,它在派生類中均不可訪問(wèn),也不存在訪問(wèn)控制屬性改變的問(wèn)題?;愔械乃接谐蓡T只能通過(guò)保護(hù)或公有的函數(shù)訪問(wèn)。l 基類的保護(hù)成員在派生類中所有的繼承方式均可直接訪問(wèn),不過(guò)私有繼承方式會(huì)把基類訪問(wèn)控制屬性是保護(hù)成員的轉(zhuǎn)換為派生類中的私有成員,而保護(hù)和公有繼承方式依然保持其為保護(hù)成員的訪問(wèn)控制屬性。l 基類的公有成員在派生類中也是可直接訪問(wèn)的,派生類中基類成員的訪問(wèn)控制屬性均隨繼承方式而改變。從橫向觀察表6-1可知,3種繼承方式都不改變從派生類訪問(wèn)基類成員的能力,但私有和保護(hù)繼承方式均會(huì)改變基類成員在派生類中的訪問(wèn)控制屬性,而只有公有繼承方式保持基類成員的
14、訪問(wèn)控制屬性在派生類中不變。在應(yīng)用中,公有繼承方式絕對(duì)是主流的派生方式,其他兩種方式使用較少。6.2 6.2 派生類派生類 如果對(duì)private、protected、public這3個(gè)關(guān)鍵字的訪問(wèn)控制能力按從高到低的順序排序,則private最高,protected次之,而public最低。派生類中,基類成員的訪問(wèn)控制屬性改變與否其實(shí)遵守如下準(zhǔn)則:“強(qiáng)者優(yōu)先”,即由基類成員在基類中的訪問(wèn)控制符和派生類在繼承基類時(shí)所使用的繼承方式符(兩者中的“強(qiáng)者”)決定其在派生類中的訪問(wèn)控制屬性?!纠?-2】3種繼承方式對(duì)訪問(wèn)控制能力的影響示例。 6.2 6.2 派生類派生類程序說(shuō)明:l 程序中定義了Base
15、基類,其中含有私有的數(shù)據(jù)privateData和函數(shù)privateFunction,受保護(hù)的數(shù)據(jù)protectedData和函數(shù)protectedFunction,公有的數(shù)據(jù)publicData和函數(shù)publicFunction、show和構(gòu)造函數(shù)。在此基礎(chǔ)上,分別用3種繼承方式定義了派生類privateDerived、protedtedDerived和publicDerived。3個(gè)派生類的結(jié)構(gòu)十分相似,除構(gòu)造函數(shù)外,callBaseFunction函數(shù)調(diào)用Base類的4個(gè)成員函數(shù)。privateFunction在3個(gè)派生類中均不能被調(diào)用,而其他函數(shù)都可以。l 在程序的主函數(shù)中,定義了3個(gè)派
16、生類的對(duì)象,并試圖通過(guò)這些對(duì)象調(diào)用基類的4個(gè)成員函數(shù)(privateFunction、protectedFunction、publicFunction和show),但僅有公有派生對(duì)象publicDerivedObj能調(diào)用公有函數(shù)publicFunction和show。 6.2 6.2 派生類派生類6.2.3 成員函數(shù)的同名覆蓋與隱藏l 改造基類成員函數(shù)是派生類在基類上擴(kuò)展功能的重要手段之一。在派生類中重新定義基類的同名成員函數(shù)后,基類中的同名成員函數(shù)將被同名覆蓋(Override)或隱藏(Hide)。l 派生類中重定義的同名成員函數(shù)的函數(shù)簽名決定了基類中的成員函數(shù)是被同名覆蓋還是被隱藏。l 同
17、名覆蓋是由于派生類與基類的同名成員函數(shù)的函數(shù)簽名相同,派生類對(duì)象在調(diào)用同名成員函數(shù)時(shí),系統(tǒng)調(diào)用派生類的同名成員函數(shù),而基類的相應(yīng)函數(shù)被遮蓋。l 隱藏是由于派生類與基類的同名成員函數(shù)的函數(shù)簽名不同(即函數(shù)名相同而形參不同),派生類對(duì)象在調(diào)用同名成員函數(shù)時(shí),系統(tǒng)只在派生類中查找,不再深入到基類。派生類的同名成員函數(shù)阻止了對(duì)基類中同名函數(shù)的訪問(wèn)。6.2 6.2 派生類派生類編譯器調(diào)用類的成員函數(shù)的方法是:根據(jù)函數(shù)名(不是函數(shù)簽名)沿著類的繼承鏈逐級(jí)向上查找相匹配的函數(shù)定義。如果在類層次結(jié)構(gòu)的某個(gè)類中找到了同名的成員函數(shù),則停止查找,否則沿著繼承鏈向上繼續(xù)查找。派生中的同名函數(shù)阻止編譯器到其基類繼續(xù)查
18、找,這就是出現(xiàn)同名覆蓋和隱藏現(xiàn)象的原因。 l 從成員函數(shù)調(diào)用的查找方法可知,同名覆蓋和隱藏基類函數(shù)的原因是由于編譯器在派生類中遇到同名函數(shù)后不再到基類中繼續(xù)查找。然而,在派生類中可利用作用域標(biāo)識(shí)符(:)直接調(diào)用基類的同名成員函數(shù),方式如下:l .:6.2 6.2 派生類派生類【例6-3】派生類中成員函數(shù)的同名覆蓋、隱藏和重載示例。6.2 6.2 派生類派生類6.2.4 派生類與基類的賦值兼容 由于派生類中包含從基類繼承的成員,因此在任何需要基類對(duì)象的地方都可以用公有派生類的對(duì)象來(lái)代替。派生類對(duì)象向基類對(duì)象、指針或引用賦值滿足以下兼容規(guī)則:l 派生類對(duì)象可以賦值給基類對(duì)象,它是把派生類對(duì)象中從對(duì)
19、應(yīng)基類中繼承來(lái)的成員賦值給基類對(duì)象。l 派生類對(duì)象的地址可以賦給指向基類的指針變量,即基類指針可以指向派生類對(duì)象。但通過(guò)該指針只能訪問(wèn)派生類中從基類繼承的成員,不能訪問(wèn)派生類中的新增成員。l 派生類對(duì)象可以代替基類對(duì)象向基類對(duì)象的引用進(jìn)行賦值或初始化。但它只能引用包含在派生類對(duì)象中基類部分的成員。6.2 6.2 派生類派生類 在對(duì)基類對(duì)象進(jìn)行適當(dāng)?shù)霓D(zhuǎn)換或增添成員函數(shù)后,基類對(duì)象能向派生類對(duì)象、指針或引用賦值。由于從基類轉(zhuǎn)換來(lái)的派生類對(duì)象缺少派生類中新增的數(shù)據(jù)成員,因而訪問(wèn)指向基類對(duì)象的派生類指針(或引用)是不安全的。 下面列出兩種轉(zhuǎn)換方法。 (1)在派生類中定義正確的轉(zhuǎn)換構(gòu)造函數(shù)或賦值運(yùn)算符重
20、載函數(shù),則能確保將基類對(duì)象賦給派生類對(duì)象語(yǔ)句通過(guò)編譯。此時(shí),派生類對(duì)象中數(shù)據(jù)成員的內(nèi)容與所定義的構(gòu)造函數(shù)或賦值運(yùn)算符重載函數(shù)相關(guān)。6.2 6.2 派生類派生類(2)用強(qiáng)制類型轉(zhuǎn)換運(yùn)算符轉(zhuǎn)換基類對(duì)象為派生類對(duì)象并賦給派生類指針或引用,格式如下: = static_cast(&); & = static_cast();l 其中static_cast運(yùn)算符的使用格式為static_cast(),功能是把轉(zhuǎn)換為的類型。用static_cast運(yùn)算符能實(shí)現(xiàn)類層次結(jié)構(gòu)中基類(父類)和派生類(子類)之間指針或引用的轉(zhuǎn)換。這種轉(zhuǎn)換分為“上行”和“下行”兩種。l 注意:將強(qiáng)制類型轉(zhuǎn)換后的基類對(duì)象
21、賦值給派生類的指針或引用,由于缺少派生類的成員,可能會(huì)導(dǎo)致程序崩潰。6.2 6.2 派生類派生類【例6-4】設(shè)計(jì)Person類和其派生類Student類,驗(yàn)證賦值兼容規(guī)則。 6.2 6.2 派生類派生類(1)在程序中,Student類是Person類的派生類,它在基類數(shù)據(jù)成員的基礎(chǔ)上增加了學(xué)號(hào)和入學(xué)成績(jī)數(shù)據(jù)成員。類中showInfo成員函數(shù)用于顯示對(duì)象中的數(shù)據(jù)。(2)主函數(shù)的最后一條語(yǔ)句studentPtr=&personObj;在編譯時(shí)出錯(cuò)。錯(cuò)誤信息為:error C2440:“=”: 無(wú)法從“Person *”轉(zhuǎn)換為“Student *”。說(shuō)明基類對(duì)象地址直接賦給派生類指針不支持。
22、如果改為studentPtr = static_cast(&personObj);,則能通過(guò)編譯。 (3)displayPersonInfo函數(shù)的形參為Person類的引用類型,在主程序中分別將基類對(duì)象personObj和派生類對(duì)象studentObj傳遞給該函數(shù),運(yùn)行結(jié)果顯示其只能調(diào)用基類中的成員函數(shù)showInfo,均只能見(jiàn)到Person類的部分?jǐn)?shù)據(jù)。(4)personObj=studentObj;語(yǔ)句的結(jié)果是personObj中數(shù)據(jù)成員的值和studentObj中基類部分?jǐn)?shù)據(jù)成員的值完全相同。 6.3 6.3 派生類的構(gòu)造與析構(gòu)派生類的構(gòu)造與析構(gòu) 在派生類對(duì)象中,數(shù)據(jù)成員分為兩類
23、:一類是繼承于基類的數(shù)據(jù)成員;另一類是新添加的數(shù)據(jù)成員,包含其他類的成員對(duì)象。派生類對(duì)象中數(shù)據(jù)成員繼承了基類數(shù)據(jù),因而構(gòu)造函數(shù)需要負(fù)責(zé)它們的初始化,派生類構(gòu)造函數(shù)的定義格式如下:派生類名() : 基類名1(),., 基類名m(),成員對(duì)象名1(),.,成員對(duì)象名n() ;6.3 6.3 派生類的構(gòu)造與析構(gòu)派生類的構(gòu)造與析構(gòu)其中:(1)基類名1(), ., 基類名m()為基類成員的初始化表,成員對(duì)象名1(), ., 成員對(duì)象名n()為成員對(duì)象初始化表。派生類中新增的類型為基本類型的數(shù)據(jù)成員也可采用成員對(duì)象的方式進(jìn)行初始化。(2)派生類構(gòu)造函數(shù)中所列出的基類名i(),在基類中需要有相匹配的構(gòu)造函數(shù)
24、。中包含其所有基類、成員對(duì)象和新增成員初始化所需的參數(shù)。(3)冒號(hào)后面的基類名和對(duì)象名之間用逗號(hào)分隔,其順序沒(méi)有嚴(yán)格的限制。l 在創(chuàng)建派生類對(duì)象時(shí),構(gòu)造函數(shù)的調(diào)用順序?yàn)椋?按照在派生類定義時(shí)的先后次序調(diào)用基類構(gòu)造函數(shù)。 按照在類定義中排列的先后順序依次調(diào)用成員對(duì)象的構(gòu)造函數(shù)。 執(zhí)行派生類構(gòu)造函數(shù)中的操作。l 派生類對(duì)象在撤消時(shí)是按照構(gòu)造函數(shù)調(diào)用相反的次序調(diào)用類的析構(gòu)函數(shù)。首先調(diào)用派生類析構(gòu)函數(shù),清除派生類中新增的數(shù)據(jù)成員;其次調(diào)用成員對(duì)象析構(gòu)函數(shù),清除派生類對(duì)象中的成員對(duì)象;最后調(diào)用基類的析構(gòu)函數(shù),清除從基類繼承來(lái)的數(shù)據(jù)成員。6.3 6.3 派生類的構(gòu)造與析構(gòu)派生類的構(gòu)造與析構(gòu)【例6-5】設(shè)計(jì)
25、Teacher類,它繼承于Person類并組合了Date類。演示派生類對(duì)象在構(gòu)造和析構(gòu)時(shí),基類和成員對(duì)象構(gòu)造與析構(gòu)函數(shù)的調(diào)用情況。程序說(shuō)明:l 從程序運(yùn)行結(jié)果可見(jiàn),雖然在Teacher派生類構(gòu)造函數(shù)定義中成員對(duì)象(dateOfWork)聲明在基類(Person)前,但依然是基類構(gòu)造函數(shù)先被執(zhí)行。此外,運(yùn)行結(jié)果顯示析構(gòu)函數(shù)的調(diào)用次序正好與構(gòu)造函數(shù)調(diào)用順序相反。l 派生類構(gòu)造Teacher(char *n, bool s, int y, int m, int d, int en, char *pt)的總參數(shù)表中參數(shù)的包括基類構(gòu)造函數(shù)Person(char *n, bool s)和成員對(duì)象構(gòu)造函數(shù)D
26、ate(int y, int m, int d)的參數(shù)。l 在派生類構(gòu)造函數(shù)定義中,基類Person的聲明格式是Person(n, s),用Date類定義的成員對(duì)象dateOfWork的聲明格式是dateOfWork(y, m, d)。6.3 6.3 派生類的構(gòu)造與析構(gòu)派生類的構(gòu)造與析構(gòu) C+支持從兩個(gè)及以上基類共同派生出新的派生類, 這 種 繼 承 結(jié) 構(gòu) 被 稱 為 多 重 繼 承 ( M u l t i p l e Inheritance)或多繼承。多重繼承能方便地描述事物的多種特征,能方便地支持代碼復(fù)用,具有結(jié)構(gòu)簡(jiǎn)單清晰的優(yōu)點(diǎn)。 6.4 6.4 多重繼承與虛基類多重繼承與虛基類 6.4
27、 6.4 多重繼承與虛基類多重繼承與虛基類6.4.1 多重繼承 多重繼承的派生類繼承于多個(gè)基類,在派生類定義時(shí),多個(gè)基類之間用逗號(hào)分隔。派生類對(duì)象初始化時(shí),將首先調(diào)用基類的構(gòu)造函數(shù),其調(diào)用順序是參照定義中的次序,如: class C : public A, public B public: C() : B(), A() cout Call C Constructor! endl; ; 基類A的構(gòu)造函數(shù)先調(diào)用,盡管在構(gòu)造函數(shù)聲明中基類B的構(gòu)造函數(shù)在基類A的前面。 6.4 6.4 多重繼承與虛基類多重繼承與虛基類 由于多重繼承的基類不止一個(gè),而不同的類其數(shù)據(jù)成員和成員函數(shù)有可能同名,此時(shí)派生類繼承
28、了不同基類的同名成員,會(huì)出現(xiàn)無(wú)法訪問(wèn)的二義性問(wèn)題?!纠?-6】手機(jī)類和MP4播放器類為基類定義音樂(lè)手機(jī)類,并測(cè)試。 6.4 6.4 多重繼承與虛基類多重繼承與虛基類程序說(shuō)明:l MobilePhone類和MusicPlayer類均擁有show成員函數(shù),在派生類中訪問(wèn)show函數(shù)必須的指明是屬于哪個(gè)基類的成員函數(shù),方法是MobilePhone:show();,其中“:”是作用域標(biāo)識(shí)符。l 語(yǔ)句myObj.show();在編譯時(shí)出錯(cuò),所報(bào)錯(cuò)誤為:對(duì)“show”的訪問(wèn)不明確。如果將改語(yǔ)句為myObj.MusicPlayer:show();,則能通過(guò)編譯。6.4 6.4 多重繼承與虛基類多重繼承與虛基
29、類6.4.2 虛基類 在例程6-6中,手機(jī)類和播放器類均含有商標(biāo)和價(jià)格數(shù)據(jù)成員,并且在派生類中包含了兩份同樣的數(shù)據(jù)。這種設(shè)計(jì)不僅浪費(fèi)存儲(chǔ)空間,而且會(huì)帶來(lái)數(shù)據(jù)更新的一致性問(wèn)題。例如,若音樂(lè)手機(jī)降價(jià)了,則需要同時(shí)修改兩處price私有數(shù)據(jù)。一種比較自然的設(shè)計(jì)方法是定義一個(gè)商品類,其中包含商標(biāo)和價(jià)格數(shù)據(jù),而手機(jī)類和播放器類分別繼承于商品類。派生類的層次結(jié)構(gòu)如圖所示。6.4 6.4 多重繼承與虛基類多重繼承與虛基類l 在多重繼承的類繼承層次結(jié)構(gòu)中,繼承于兩個(gè)不同基類的派生類,由于其基類又派生于同一個(gè)基類(不一定是直接基類),故可能出現(xiàn)如圖6-5所示的“鉆石繼承”(又稱菱形繼承)情況。此時(shí)商品類中的數(shù)據(jù)
30、成員(如價(jià)格price)分別被其派生類手機(jī)類和播放器類所繼承,而音樂(lè)手機(jī)類又多重繼承于手機(jī)類和播放器類,因此,商品類的數(shù)據(jù)成員price分別通過(guò)手機(jī)類和播放器類派生給音樂(lè)手機(jī)類,同樣的數(shù)據(jù)成員在音樂(lè)手機(jī)派生類對(duì)象中將出現(xiàn)兩個(gè),并且存儲(chǔ)地址也不相同。這樣不僅浪費(fèi)存儲(chǔ)空間,而且還會(huì)因?yàn)樾枰S護(hù)數(shù)據(jù)的一致性增加額外的開(kāi)銷。l 下面的示例說(shuō)明了多重繼承可能引發(fā)“鉆石繼承”問(wèn)題?!纠?-7】多重繼承中存在的“鉆石繼承”和數(shù)據(jù)同步問(wèn)題示例。 6.4 6.4 多重繼承與虛基類多重繼承與虛基類l 跟蹤與觀察:(1) 主函數(shù)中執(zhí)行了myObj.MusicPlayer:setPrice(500);,使得繼承于Mu
31、sicPlayer的price數(shù)據(jù)的值為500,因而運(yùn)行結(jié)果顯示出1800和500兩個(gè)不同的價(jià)格。(2) 從圖6-6可知,基類繼承來(lái)的數(shù)據(jù)成員name和price在音樂(lè)手機(jī)派生類對(duì)象myObj中分別存儲(chǔ)了兩份,其中,從MobilePhone類繼承的name成員的存儲(chǔ)地址為0 x002ff85c,price成員的存儲(chǔ)地址為0 x002ff87c,而從MusicPlayer類繼承的name成員的存儲(chǔ)地址為0 x002ff8a0,price成員的存儲(chǔ)地址為0 x002ff8c0,并且兩個(gè)price成員的值不相同。6.4 6.4 多重繼承與虛基類多重繼承與虛基類l 多重繼承中存在的鉆石繼承結(jié)構(gòu)將導(dǎo)致基
32、類的數(shù)據(jù)成員在派生類對(duì)象中重復(fù)出現(xiàn)。為解決多重繼承在路徑匯聚點(diǎn)上的派生類因從不同路徑繼承了某個(gè)基類多次而產(chǎn)生重復(fù)繼承的問(wèn)題,C+語(yǔ)言通過(guò)引入虛基類(Virtual Base Class)來(lái)支持派生類對(duì)象在內(nèi)存中僅有基類數(shù)據(jù)成員的一份拷貝,以消除鉆石繼承所產(chǎn)生的數(shù)據(jù)重復(fù)存儲(chǔ)問(wèn)題。l 虛基類定義的語(yǔ)法非常簡(jiǎn)單,只需用virtual限定符在派生類定義時(shí)將基類的繼承方式聲明為虛擬的即可。例如: class MobilePhone : virtual public Merchandise . 其中virtual和public關(guān)鍵字的次序可任意。6.4 6.4 多重繼承與虛基類多重繼承與虛基類 下面的程序是在例6-7的基礎(chǔ)上,通過(guò)定義虛基類解決派生類對(duì)象中基類數(shù)據(jù)成員重復(fù)存儲(chǔ)的問(wèn)題。 【例6-8】用虛基類解決“
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 人物肖像描繪作文10篇
- 媒體發(fā)布服務(wù)合同書
- 八鋼公司建軍節(jié)活動(dòng)方案
- 公交公司文體活動(dòng)方案
- 公交活動(dòng)優(yōu)惠活動(dòng)方案
- 公交集團(tuán)植樹(shù)節(jié)活動(dòng)方案
- 農(nóng)業(yè)合作網(wǎng)絡(luò)技術(shù)推廣服務(wù)協(xié)議
- 六年級(jí)童話寓言作文雪中送炭800字9篇
- 公共文明健康活動(dòng)方案
- 給新老師的一封信400字(8篇)
- 2019年盲樣考核方案匯總
- 部編《小馬過(guò)河》完美課件1
- 天醫(yī)門符法修煉與祝由移病法
- 粒子加速器控制系統(tǒng)課件1-概述課件
- 義務(wù)教育科學(xué)課程標(biāo)準(zhǔn)(2022年版)
- 美國(guó)CLIA88質(zhì)量要求
- 年公開(kāi)選拔副科級(jí)領(lǐng)導(dǎo)干部試題及答案
- 喉鏡使用簡(jiǎn)單介紹PPT課件
- 不停車稱重系統(tǒng)
- 中國(guó)重汽集團(tuán)章丘工業(yè)園簡(jiǎn)介-12頁(yè)word資料
- 檢驗(yàn)科生物安全審批記錄
評(píng)論
0/150
提交評(píng)論