C 程序設(shè)計(jì)課件:第八章 繼承與多態(tài)_第1頁(yè)
C 程序設(shè)計(jì)課件:第八章 繼承與多態(tài)_第2頁(yè)
C 程序設(shè)計(jì)課件:第八章 繼承與多態(tài)_第3頁(yè)
C 程序設(shè)計(jì)課件:第八章 繼承與多態(tài)_第4頁(yè)
C 程序設(shè)計(jì)課件:第八章 繼承與多態(tài)_第5頁(yè)
已閱讀5頁(yè),還剩111頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、繼承(inheritance):該機(jī)制是面向?qū)ο蟪绦蛟O(shè)計(jì)使代碼可以復(fù)用的最重要的手段,它允許程序員在保持原有類特性的基礎(chǔ)上進(jìn)行擴(kuò)展,增加功能。這樣產(chǎn)生新的類,稱派生類。繼承呈現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計(jì)的層次結(jié)構(gòu)。體現(xiàn)了由簡(jiǎn)單到復(fù)雜的認(rèn)識(shí)過程。第八章 繼承與多態(tài)多態(tài)性(polymorphism):多態(tài)性包括靜態(tài)的多態(tài)性和動(dòng)態(tài)的多態(tài)性。前者亦稱編譯時(shí)的多態(tài)性,包括函數(shù)的重載和運(yùn)算符的重載。后者亦稱運(yùn)行時(shí)的多態(tài)性,這是以虛函數(shù)為基礎(chǔ)的,是面向?qū)ο蟪绦蛟O(shè)計(jì)的標(biāo)志性特征。 體現(xiàn)了類推和比喻的思想方法。 第八章 繼承與多態(tài)8.1 繼承與派生的概念 8.4 虛基類 (選讀) 8.3 多重繼承與派生類成員標(biāo)識(shí) (選

2、讀) 8. 6 多態(tài)性與虛函數(shù) 8.5 派生類應(yīng)用討論 8.2 派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù) 附錄: UML類圖中的依賴關(guān)系附錄:用UML類圖表示派生8.1 繼承與派生的概念層次概念是計(jì)算機(jī)的重要概念。通過繼承(inheritance)的機(jī)制可對(duì)類(class)分層,提供類型/子類型的關(guān)系。 C+通過類派生(class derivation)的機(jī)制來支持繼承。被繼承的類稱為基類(base class)或超類(superclass),新的類為派生類(derived class)或子類(subclass)。基類和派生類的集合稱作類繼承層次結(jié)構(gòu)(hierarchy)。 如果基類和派生類共享相同的公有接

3、口,則派生類被稱作基類的子類型(subtype)。 層次概念:派生反映了事物之間的聯(lián)系,事物的共性與個(gè)性之間的關(guān)系。 派生與獨(dú)立設(shè)計(jì)若干相關(guān)的類,前者工作量少,重復(fù)的部分可以從基類繼承來,不需要單獨(dú)編程。 8.1 繼承與派生的概念8.1.1 類的派生與繼承 8. 1.2 公有派生與私有派生 派生類的定義:class 派生類名:訪問限定符 基類名1,訪問限定符 基類名2,訪問限定符 基類名n private: 成員表1; /派生類增加或替代的私有成員public:成員表2; /派生類增加或替代的公有成員protected:成員表3; /派生類增加或替代的保護(hù)成員;/分號(hào)不可少其中基類1,基類2,

4、是已聲明的類。 在派生類定義的類體中給出的成員稱為派生類成員,它們是新增加成員,它們給派生類添加了不同于基類的新的屬性和功能。派生類成員也包括取代基類成員的更新成員。8.1.1 類的派生與繼承8.1.1 類的派生與繼承訪問限定符兩方面含義:派生類成員(新增成員)函數(shù)對(duì)基類(繼承來的)成員的訪問(調(diào)用和操作),和從派生類對(duì)象之外對(duì)派生類對(duì)象中的基類成員的訪問。放在后面討論。公有派生限制最少,是派生的主流。訪問限定符:基類名前的訪問限定符,是對(duì)基類成員進(jìn)一步的限制。訪問控制也是三種:公有(public)方式,亦稱公有繼承保護(hù)(protected)方式,亦稱保護(hù)繼承私有(private)方式, 亦稱

5、私有繼承。 基類1基類2基類n派生類1派生類2基類派生類1派生類2(a)多重繼承 (b)單繼承 圖8.1 多重繼承與單繼承 一個(gè)基類可以直接派生出多個(gè)派生類 派生類可以由多個(gè)基類共同派生出來,稱多重繼承。8.1.1 類的派生與繼承多重繼承:如果一個(gè)派生類可以同時(shí)有多個(gè)基類,稱為多重繼承(multiple-inheritance),這時(shí)的派生類同時(shí)得到了多個(gè)已有類的特征。單繼承:派生類只有一個(gè)直接基類的情況稱為單繼承(single-inheritance)。8.1.1 類的派生與繼承 在派生過程中,派生出來的新類同樣可以作為基類再繼續(xù)派生出更新的類,依此類推形成一個(gè)層次結(jié)構(gòu)。直接參與派生出某類稱

6、為直接基類,而基類的基類,以及更深層的基類稱為間接基類。類族: 同時(shí)一個(gè)基類可以直接派生出多個(gè)派生類。這樣形成了一個(gè)相互關(guān)聯(lián)的類族。如MFC就是這樣的族類,它由一個(gè)CObject類派生出200個(gè)MFC類中的絕大多數(shù)。 多層次繼承:編制派生類時(shí)可分四步 吸收基類的成員 改造基類成員 發(fā)展新成員 重寫構(gòu)造函數(shù)與析構(gòu)函數(shù) 8.1.1 類的派生與繼承不論是數(shù)據(jù)成員,還是函數(shù)成員,除構(gòu)造函數(shù)與析構(gòu)函數(shù)外全盤接收 聲明一個(gè)和某基類成員同名的新成員,派生類中的新成員就屏蔽了基類同名成員派生類新成員必須與基類成員不同名,它的加入保證派生類在功能上有所發(fā)展。 派生編程步驟:8.1.1 類的派生與繼承第二步中,新

7、成員如是成員函數(shù),參數(shù)表和返回值也完全一樣,稱為同名覆蓋(Override),否則是重載 。第三步中,獨(dú)有的新成員才是繼承與派生的核心特征。第四步是重寫構(gòu)造函數(shù)與析構(gòu)函數(shù),派生類不繼承這兩種函數(shù)。不管原來的函數(shù)是否可用一律重寫可免出錯(cuò)。方式類似聚合含成員對(duì)象的類的構(gòu)造函數(shù)。詳細(xì)內(nèi)容后文討論?!纠?.1】由在冊(cè)人員類公有派生學(xué)生類【例8.1】由在冊(cè)人員類公有派生學(xué)生類。我們希望基類和派生類共享相同的公有接口,只能采用公有派生來實(shí)現(xiàn)?;悾篶lass Personstring IdPerson;/身份證號(hào),18位數(shù)字string Name;/姓名Tsex Sex; /性別enum Tsexmid,

8、man,woman;int Birthday;/生日,格式1986年8月18日寫作19860818string HomeAddress;/家庭地址public:Person(string, string,Tsex,int, string);/構(gòu)造函數(shù) Person(); /默認(rèn)的構(gòu)造函數(shù) Person(); /析構(gòu)函數(shù)【例8.1】由在冊(cè)人員類公有派生學(xué)生類void SetName(string); /修改名字string GetName()return Name; /提取名字void SetSex(Tsex sex)Sex=sex; /修改性別Tsex GetSex()return Sex;

9、/提取性別void SetId(string id)IdPerson=id;/修改身份證號(hào)string GetId()return IdPerson; /提取身份證號(hào)void SetBirth(int birthday)Birthday=birthday; /修改生日int GetBirth()return Birthday; /提取生日void SetHomeAdd(string ); /修改住址string GetHomeAdd()return HomeAddress; /提取住址void PrintPersonInfo(); /輸出個(gè)人信息;/接口函數(shù):【例8.1】由在冊(cè)人員類公有派生學(xué)

10、生類派生的學(xué)生類:class Student:public Person /定義派生的學(xué)生類 string NoStudent; /學(xué)號(hào) course cs30; /30門課程與成績(jī)public: Student(string id, string name,Tsex sex,int birthday, string homeadd, string nostud);/注意派生類構(gòu)造函數(shù)聲明方式 Student(); /默認(rèn)派生類構(gòu)造函數(shù) Student(); /派生類析構(gòu)函數(shù) SetCourse(string ,int); /課程設(shè)置 int GetCourse(string ); /查找成績(jī)

11、 void PrintStudentInfo(); /打印學(xué)生情況;struct course string coursename; int grade;驗(yàn)證主函數(shù)8.2 派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)注意: 本例中標(biāo)準(zhǔn)C+字符串string是作為成員對(duì)象使用的(聚合),動(dòng)態(tài)內(nèi)存分配的構(gòu)造和析構(gòu)被封裝起來,使用十分簡(jiǎn)單。如使用動(dòng)態(tài)生成的C風(fēng)格字符串,要考慮深復(fù)制,那要復(fù)雜得多。 提倡完善的類對(duì)象封裝,不僅封裝數(shù)據(jù)和對(duì)數(shù)據(jù)的操作,而且封裝資源的動(dòng)態(tài)分配與釋放,形成一個(gè)完備的子系統(tǒng)。在一個(gè)有層次結(jié)構(gòu)的類體系中資源的動(dòng)態(tài)分配與釋放應(yīng)封裝在成員對(duì)象中,如同使用標(biāo)準(zhǔn)的string字符串類那樣。 聚合是一種完

12、善的封裝。采用成員對(duì)象將大大簡(jiǎn)化層次結(jié)構(gòu)的類體系中資源的動(dòng)態(tài)分配與釋放的處理方法,不再出現(xiàn)難度極大的多層次的深復(fù)制。8.1.2 公有派生與私有派生訪問限定符討論:派生類成員(新增成員)函數(shù)對(duì)基類(繼承來的)成員的訪問(調(diào)用和操作),和從派生類對(duì)象之外對(duì)派生類對(duì)象中的基類成員的訪問。下面進(jìn)行詳細(xì)討論:8.1.2 公有派生與私有派生不可直接訪問 不可直接訪問 private 不可直接訪問 private protected 不可直接訪問 private public 私有派生所有接口必須重寫 不可直接訪問 不可直接訪問 private 不可直接訪問 protected protected 可直接訪

13、問 public public 公有派生所有接口均可使用 在派生類對(duì)象外訪問派生類對(duì)象的基類成員 在派生類中對(duì)基類成員的訪問限定 基類中的訪問限定 派生方式 公有派生是絕對(duì)主流。 8.1.2 公有派生與私有派生保護(hù)派生:直接派生: 基類的私有成員仍是派生類的私有成員,不可直接訪問,而基類中的公有和保護(hù)成員全部成為派生類的保護(hù)成員,在派生類中可以直接訪問。但在派生類對(duì)象之外是不能直接訪問該對(duì)象的任何基類成員的。與私有派生相同。多層派生:把保護(hù)派生類作為基類或把私有派生類作為基類再作一層保護(hù)派生。在新的保護(hù)派生類中可直接訪問由保護(hù)派生傳遞過來的底層基類的公有和保護(hù)成員,而不可直接訪問由私有派生傳遞

14、來的底層基類的公有和保護(hù)成員。但在該類對(duì)象之外都不可直接訪問類對(duì)象底層基類的公有成員。合理使用保護(hù)限定方式可以在復(fù)雜的類層次關(guān)系中取一個(gè)共享訪問和成員封裝隱蔽性的折衷。派生類構(gòu)造函數(shù)的定義:派生類名:派生類名(參數(shù)總表):基類名1(參數(shù)名表1),基類名2(參數(shù)名表2),基類名n(參數(shù)名表n),成員對(duì)象名1(成員對(duì)象參數(shù)名表1),成員對(duì)象名m(成員對(duì)象參數(shù)名表m)/派生類新增成員的初始化; /所列出的成員對(duì)象名全部為新增成員對(duì)象的名字注意: 在構(gòu)造函數(shù)的聲明中,冒號(hào)及冒號(hào)以后部分必須略去。 所謂不能繼承并不是不能利用,而是把基類的構(gòu)造函數(shù)作為新的構(gòu)造函數(shù)的一部分,或者講調(diào)用基類的構(gòu)造函數(shù)?;惷?/p>

15、僅指直接基類,寫了底層基類,編譯器認(rèn)為出錯(cuò)。 冒號(hào)后的基類名,成員對(duì)象名的次序可以隨意,這里的次序與調(diào)用次序無關(guān)。 8.2 派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)派生類構(gòu)造函數(shù)各部分執(zhí)行次序: 1.調(diào)用基類構(gòu)造函數(shù),按它們?cè)谂缮惗x的先后順序,順序調(diào)用。 2.調(diào)用成員對(duì)象的構(gòu)造函數(shù),按它們?cè)陬惗x中聲明的先后順序,順序調(diào)用。3.派生類的構(gòu)造函數(shù)體中的操作。8.2 派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)注意: 在派生類構(gòu)造函數(shù)中,只要基類不是使用無參的默認(rèn)構(gòu)造函數(shù)都要顯式給出基類名和參數(shù)表。 如果基類沒有定義構(gòu)造函數(shù),則派生類也可以不定義,全部采用系統(tǒng)給定的默認(rèn)構(gòu)造函數(shù)。 如果基類定義了帶有形參表的構(gòu)造函數(shù)時(shí),派生類

16、就應(yīng)當(dāng)定義構(gòu)造函數(shù)。8.2 派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)析構(gòu)函數(shù):析構(gòu)函數(shù)的功能是作善后工作。 只要在函數(shù)體內(nèi)把派生類新增的一般成員處理好就可以了,而對(duì)新增的成員對(duì)象和基類的善后工作,系統(tǒng)會(huì)自己調(diào)用成員對(duì)象和基類的析構(gòu)函數(shù)來完成。 析構(gòu)函數(shù)各部分執(zhí)行次序與構(gòu)造函數(shù)相反,首先對(duì)派生類新增一般成員析構(gòu),然后對(duì)新增對(duì)象成員析構(gòu),最后對(duì)基類成員析構(gòu)。8.3 多重繼承與派生類成員標(biāo)識(shí)(選讀)由多個(gè)基類共同派生出新的派生類,這樣的繼承結(jié)構(gòu)被稱為多重繼承或多繼承(multiple-inheritance) 椅子床沙發(fā)(單繼承)躺椅(多重繼承)兩用沙發(fā)(多重繼承)圖8.2 椅子,床到兩用沙發(fā)多重繼承實(shí)例:在冊(cè)人

17、員學(xué)生(單繼承)教職工(單繼承)兼職教師(單繼承)教師(單繼承)行政人員(單繼承)工人(單繼承)研究生(單繼承)行政人員兼教師(多重繼承)在職研究生(多重繼承)研究生助教(多重繼承)圖8.3 大學(xué)在冊(cè)人員繼承關(guān)系8.3 多重繼承與派生類成員標(biāo)識(shí)(選讀)派生出來的新類同樣可以作為基類再繼續(xù)派生出更新的類,依此類推形成一個(gè)層次結(jié)構(gòu)。 8.3 多重繼承與派生類成員標(biāo)識(shí)(選讀)歧義性問題:參見圖8.3,比如行政人員兼教師,在其基類教師中有一個(gè)“教職工編號(hào)”,另一基類行政人員中也有一個(gè)“教職工編號(hào)”,如果只講教職工編號(hào)那么是哪一個(gè)基類中的呢?這兩者可能是一回事,但計(jì)算機(jī)系統(tǒng)并不這么認(rèn)為。進(jìn)一步,如果“教

18、職工編號(hào)” 是由兩個(gè)基類“教師”和“行政人員”共同的基類“教職工”類繼承來的,只有同一個(gè)標(biāo)識(shí)符,也不能用改標(biāo)識(shí)符來區(qū)分。 唯一標(biāo)識(shí)問題:通常采用作用域分辨符“:”:基類名:成員名; /數(shù)據(jù)成員基類名:成員名(參數(shù)表); /函數(shù)成員 class EGStudent int No在職學(xué)號(hào) class GStudent int No研究生號(hào) .class Student int No學(xué)生號(hào) . class Person int No身份證號(hào) .class Employee int No工作證號(hào) .class Person int No身份證號(hào) .圖8.4(a)在職研究生派生類關(guān)系 定義EGStude

19、nt類對(duì)象EGStudent1,并假定派生全部為公有派生,而int No全為公有成員:EGStud1.No /在職學(xué)號(hào)EGStud1.GStudent:No /研究生號(hào)EGStud1.GStudent.Student:No /學(xué)生號(hào) EGStud1.GStudent.Student. Person:No /身份證號(hào)EGStud1.Employee:No /工作證號(hào)EGStud1.Employee.Person:No /身份證號(hào)兩個(gè)身份證號(hào)從邏輯上講應(yīng)是一回事,但是物理上是分配了不同內(nèi)存空間,是兩個(gè)變量,請(qǐng)參見圖8.4(b)。Person Person StudentEmployee GStud

20、ent EGStudentPerson成員 Person成員 Student新成員 GStudent新成員 Employee新成員 EGStudent新成員 圖8.4(b)在職研究生派生類存儲(chǔ)圖 建議采用有確定字面意思的標(biāo)識(shí)符,它可以被編譯器簡(jiǎn)單區(qū)分出來。 如果class Person的身份證號(hào)標(biāo)識(shí)為int IdPerson,則寫為:EGStud1.GStudent:IdPersonEGStud1.Employee:IdPerson不必標(biāo)出那么多層次的類,但寫EGStud1:IdPerson是錯(cuò)的。 作用域分辨符不能嵌套使用,如:EGStud1.GStudent:Student:No/學(xué)生號(hào)E

21、GStud1.GStudent:Student:Person:No /身份證號(hào)是錯(cuò)誤的。 8.3 多重繼承與派生類成員標(biāo)識(shí)(選讀)8.3 多重繼承與派生類成員標(biāo)識(shí)(選讀)一般數(shù)據(jù)成員總是私有成員,派生類對(duì)基類的訪問只能間接進(jìn)行。訪問身份證號(hào),應(yīng)通過class Person中的公有成員函數(shù)(接口)GetNo()和SetNo()進(jìn)行:EGStud1.Employee.Person:SetNo(no);no=EGStud1.Employee.Person:GetNo();注意:【例8.2】由圓和高多重繼承派生出圓錐。 因?yàn)楣信缮鷷r(shí),在派生類中不可以直接訪問基類的私有成員,但可以直接訪問基類的保護(hù)成

22、員,當(dāng)需要在派生類中訪問基類的數(shù)據(jù)成員時(shí),可以將它們定義為保護(hù)的,而不是私有的。 本例中類Circle為圓;類Line為高;類Cone為圓錐,由Circle和Line公有派生而來。在Cone類中,Circle和Line類的接口完全不變,可以直接調(diào)用,這就是公有派生的優(yōu)點(diǎn)。在Cone的成員函數(shù)中可直接訪問Circle和Line中的公有成員和保護(hù)成員。 【例8.2】由圓和高多重繼承派生出圓錐檢證主程序:圓類Circle定義高類Line定義圓錐類Cone定義虛基類的引入:在圖8.4中,兩個(gè)身份證號(hào)顯然是不合理的??梢园裞lass Person這個(gè)共同基類設(shè)置為虛基類,這樣就僅有一個(gè)Person基類成

23、員,從不同路徑繼承來的同名數(shù)據(jù)成員(身份證號(hào))在內(nèi)存中就是同一個(gè)數(shù)據(jù)。 8.4 虛基類(選讀)注意:virtual 關(guān)鍵字只對(duì)緊隨其后的基類名起作用:class Student:virtual public Person.;class Employee:virtual public Person.;虛基類(virtual base class)定義:class 派生類名:virtual 訪問限定符 基類類名.;class 派生類名:訪問限定符 virtual 基類類名.;8.4 虛基類(選讀)圖8.5 采用虛基類后在職研究生類儲(chǔ)存圖StudentGStudentEGStudentPersonS

24、tudent新成員GStudent新成員PersonEmployee新成員Person成員EGStudent新成員PersonPersonEmployee這種繼承稱為虛擬繼承虛擬繼承:在Person的位置上放的是指針,兩個(gè)指針都指向Person成員存儲(chǔ)的內(nèi)存。這種繼承稱為虛擬繼承(virtual inheritance)。8.4 虛基類(選讀)派生類名:派生類名(參數(shù)總表):基類名1(參數(shù)名表1),基類名2(參數(shù)名表2),基類名n(參數(shù)名表n),成員對(duì)象名1(成員對(duì)象參數(shù)名表1),成員對(duì)象名m(成員對(duì)象參數(shù)名表m),底層虛基類名1(參數(shù)名表1), 底層虛基類名r(參數(shù)名表r)/派生類新增成員的

25、初始化; /所列出的成員對(duì)象名全部為新增成員對(duì)象的名字在多層虛擬繼承構(gòu)造函數(shù)中,基類名不僅要列出直接基類,而且要列出底層虛基類,否則編譯器認(rèn)為出錯(cuò)。如不是虛擬繼承只能列直接基類。虛擬繼承的構(gòu)造函數(shù):8.4 虛基類(選讀)在派生類對(duì)象的創(chuàng)建中:首先是虛基類的構(gòu)造函數(shù)并按它們聲明的順序構(gòu)造。第二批是非虛基類的構(gòu)造函數(shù)按它們聲明的順序調(diào)用。第三批是成員對(duì)象的構(gòu)造函數(shù)。最后是派生類自己的構(gòu)造函數(shù)被調(diào)用。構(gòu)造函數(shù)執(zhí)行次序:8.4 虛基類(選讀)【例8.3】在采用虛基類的多重繼承中構(gòu)造與析構(gòu)的次序。class Objectpublic:Object()coutconstructor Objectn;Obj

26、ect()coutdeconstructor Objectn;class Bclass1public:Bclass1()coutconstructor Bclass1n;Bclass1()coutdeconstructor Bclass1n;class Bclass2public:Bclass2()coutconstructor Bclass2n;Bclass2()coutdeconstructor Bclass2n;8.4 虛基類(選讀)【例8.3】在采用虛基類的多重繼承中,構(gòu)造與析構(gòu)的次序。class Bclass3public:Bclass3()coutconstructor Bclas

27、s3n;Bclass3()coutdeconstructor Bclass3n;class Dclass:public Bclass1,virtual Bclass3,virtual Bclass2 Object object;public: Dclass():object(),Bclass2(),Bclass3(),Bclass1() cout派生類建立!n; Dclass()cout派生類析構(gòu)!n;int main() Dclass dd; coutPrintStudentInfo();pper4=pstu4;delete pper4;/用基類指針撤銷派生類,動(dòng)態(tài)生成的對(duì)象必須顯式撤銷8.

28、6.1 虛函數(shù)的定義在主函數(shù)中添加以下內(nèi)容: 通過在析構(gòu)函數(shù)中加顯示語句發(fā)現(xiàn)先調(diào)Student析構(gòu)函數(shù),后調(diào)Person析構(gòu)函數(shù)。 這里再次強(qiáng)調(diào)動(dòng)態(tài)生成的對(duì)象必須顯式撤銷。純虛函數(shù): 純虛函數(shù)(pure virtual function)是指被標(biāo)明為不具體實(shí)現(xiàn)的虛擬成員函數(shù)。它用于這樣的情況:定義一個(gè)基類時(shí),會(huì)遇到無法定義基類中虛函數(shù)的具體實(shí)現(xiàn),其實(shí)現(xiàn)依賴于不同的派生類。8.6.2 純虛函數(shù)純虛函數(shù)的定義:virtual 返回類型 函數(shù)名(參數(shù)表)=0;含有純虛函數(shù)的基類是不能用來定義對(duì)象的。純虛函數(shù)沒有實(shí)現(xiàn)部分,不能產(chǎn)生對(duì)象,所以含有純虛函數(shù)的類是抽象類。1 定義純虛函數(shù)時(shí),不能定義虛函數(shù)的

29、實(shí)現(xiàn)部分。即使是函數(shù)體為空也不可以,函數(shù)體為空就可以執(zhí)行,只是什么也不做就返回。但根本不能調(diào)用純虛函數(shù)。2 “=0”表明程序員將不定義該函數(shù),函數(shù)聲明是為派生類保留一個(gè)位置?!?0”本質(zhì)上是將指向函數(shù)體的指針定為NULL。3 在派生類中必須有重新定義的純虛函數(shù)的函數(shù)體,這樣的派生類才能用來定義對(duì)象。8.6.2 純虛函數(shù)定義純虛函數(shù)的要點(diǎn):【例8.8】學(xué)校對(duì)在冊(cè)人員進(jìn)行獎(jiǎng)勵(lì),依據(jù)是業(yè)績(jī)分,但是業(yè)績(jī)分的計(jì)算方法只能對(duì)具體人員進(jìn)行,如學(xué)生,教師,行政人員,工人,算法都不同,所以可以將在冊(cè)人員類作為一個(gè)抽象類,業(yè)績(jī)計(jì)算方法作為一個(gè)純虛函數(shù)。在主函數(shù)中全部用指向基類的指針來調(diào)用8.6.2 純虛函數(shù)業(yè)績(jī)分

30、基類定義業(yè)績(jī)分學(xué)生派生類定義業(yè)績(jī)分教師派生類定義驗(yàn)證主函數(shù)【例8.9】用虛函數(shù)來實(shí)現(xiàn)辛普生法求函數(shù)的定積分。8.6.2 純虛函數(shù)純虛函數(shù)實(shí)現(xiàn)通用算法:辛普生法求定積分類在派生類中加被積函數(shù):驗(yàn)證主函數(shù)8.6.3 繼承與多態(tài)的應(yīng)用單鏈表派生類(選讀)【例8.10】通用單鏈表派生類。第一步改造【例7.4】的頭文件,不采用模板類,而采用虛函數(shù)實(shí)現(xiàn)多態(tài)性,達(dá)到通用的目的。結(jié)點(diǎn)類數(shù)據(jù)域被改造為指針,而把數(shù)據(jù)放在一個(gè)抽象類中,由指針與之建立聯(lián)系。數(shù)據(jù)域(指向抽象數(shù)據(jù)類的指針)由抽象類派生的數(shù)據(jù)類對(duì)象(如串對(duì)象)指針域(指向下一結(jié)點(diǎn))結(jié)點(diǎn)類對(duì)象動(dòng)態(tài)建立的數(shù)據(jù)類對(duì)象圖8.9 結(jié)點(diǎn)構(gòu)造class Object

31、/數(shù)據(jù)類為抽象類public: Object() virtual bool operator(Object &)=0; /純虛函數(shù),參數(shù)必須為引用或指針 virtual bool operator!=(Object &)=0; /純虛函數(shù),參數(shù)必須為引用或指針 virtual void Print()=0; /純虛函數(shù) virtual Object() ; /析構(gòu)函數(shù)可為虛函數(shù),構(gòu)造函數(shù)不行8.6.3 繼承與多態(tài)的應(yīng)用單鏈表派生類(選讀)結(jié)點(diǎn)組織,采用結(jié)點(diǎn)類加數(shù)據(jù)類數(shù)據(jù)類定義:本題要點(diǎn):采用虛函數(shù)實(shí)現(xiàn)多態(tài)性,達(dá)到通用的目的。堆內(nèi)存的分配與釋放,關(guān)鍵不是創(chuàng)建,而是釋放!說明:數(shù)據(jù)抽象類中含有三個(gè)

32、純虛函數(shù):輸出函數(shù)和兩個(gè)比較函數(shù)。當(dāng)抽象類在派生時(shí)重新定義三個(gè)純虛函數(shù),可以進(jìn)行各種類型,包括類和結(jié)構(gòu)對(duì)象的比較和輸出。本例介紹程序總體組成為主,鏈表的操作由學(xué)生自己仔細(xì)閱讀。8.6.3 繼承與多態(tài)的應(yīng)用單鏈表派生類(選讀)抽象類中的析構(gòu)函數(shù)也是虛函數(shù),這一點(diǎn)非常重要。當(dāng)由結(jié)點(diǎn)類指向抽象基類的指針刪除釋放動(dòng)態(tài)分配的由抽象類派生的數(shù)據(jù)類對(duì)象時(shí),必須由數(shù)據(jù)類自定義的虛析構(gòu)函數(shù)來釋放該類對(duì)象數(shù)據(jù)部分占用內(nèi)存。 Class Node Object* info; /數(shù)據(jù)域用指針指向數(shù)據(jù)類對(duì)象 Node* link; /指針域public: Node(); /生成頭結(jié)點(diǎn)的構(gòu)造函數(shù) Node(); /析構(gòu)函

33、數(shù) void InsertAfter(Node* P); /在當(dāng)前結(jié)點(diǎn)后插入一個(gè)結(jié)點(diǎn) Node* RemoveAfter(); /刪除當(dāng)前結(jié)點(diǎn)的后繼結(jié)點(diǎn),返回該結(jié)點(diǎn)備用 void Linkinfo(Object* obj); /把數(shù)據(jù)對(duì)象連接到結(jié)點(diǎn) friend class List; /以List為友元類,List可直接訪問Node的私有函數(shù),;8.6.3 繼承與多態(tài)的應(yīng)用單鏈表派生類(選讀)結(jié)點(diǎn)類定義:class List Node *head,*tail; /鏈表頭指針和尾指針public: List(); /構(gòu)造函數(shù),生成頭結(jié)點(diǎn)(空鏈表) List(); /析構(gòu)函數(shù) void Make

34、Empty(); /清空鏈表,只余表頭結(jié)點(diǎn) Node* Find(Object & obj); /搜索數(shù)據(jù)域與定值相同的結(jié)點(diǎn),返回該結(jié)點(diǎn)的地址 int Length(); /計(jì)算單鏈表長(zhǎng)度 void PrintList(); /打印鏈表的數(shù)據(jù)域 void InsertFront(Node* p); /可用來向前生成鏈表 void InsertRear(Node* p); /可用來向后生成鏈表 void InsertOrder(Node* p); /按升序生成鏈表 Node* CreatNode(); /創(chuàng)建一個(gè)結(jié)點(diǎn)(孤立結(jié)點(diǎn)) Node* DeleteNode(Node* p); ; /刪除指

35、定結(jié)點(diǎn)8.6.3 繼承與多態(tài)的應(yīng)用單鏈表派生類(選讀)鏈表類定義:第二步,取代模板定義泛型類型為具體類型(包括類)的步驟是由抽象類派生數(shù)據(jù)類。數(shù)據(jù)類的數(shù)據(jù)采用字符類串string,動(dòng)態(tài)分配和釋放內(nèi)存都在string類中完成。為了完成數(shù)據(jù)類的比較和輸出,超載了比較運(yùn)算符和輸出函數(shù)(虛函數(shù))。數(shù)據(jù)類的比較實(shí)際是字符串string的比較。 8.6.3 繼承與多態(tài)的應(yīng)用單鏈表派生類(選讀)class StringObject:public Object string sptr;public: StringObject() sptr=; StringObject(string s)sptr=s; Str

36、ingObject(); /析構(gòu)函數(shù) bool operator(Object &); /大于函數(shù) bool operator!=(Object &); /不等于函數(shù) void Print(); /打印函數(shù);驗(yàn)證主函數(shù)運(yùn)行結(jié)果分析與比較: 在該程序中,特別要仔細(xì)揣摩堆內(nèi)存的分配與釋放。刪除一個(gè)結(jié)點(diǎn)時(shí)系統(tǒng)自動(dòng)調(diào)用結(jié)點(diǎn)類析構(gòu)函數(shù)釋放結(jié)點(diǎn)占用的動(dòng)態(tài)內(nèi)存,而結(jié)點(diǎn)類析構(gòu)函數(shù)自動(dòng)調(diào)用數(shù)據(jù)域類虛析構(gòu)函數(shù),數(shù)據(jù)域類析構(gòu)函數(shù)自動(dòng)調(diào)用string類的析構(gòu)函數(shù)釋放所占用的動(dòng)態(tài)內(nèi)存。一環(huán)套一環(huán),一步都不能錯(cuò)。這是使用動(dòng)態(tài)內(nèi)存分配的關(guān)鍵。即關(guān)鍵不是創(chuàng)建,而是釋放! 運(yùn)行時(shí)的多態(tài)性需要維護(hù)一個(gè)動(dòng)態(tài)指針表才能正確指向各相關(guān)

37、類中的同名虛函數(shù)。所以多態(tài)與模板比較,模板的效率更高,標(biāo)準(zhǔn)模板庫(kù)中用容器來泛型化數(shù)據(jù)結(jié)構(gòu)中的許多算法。對(duì)數(shù)據(jù)結(jié)構(gòu)的使用當(dāng)然借助模板庫(kù)。多態(tài)不適用于性能要求很高的實(shí)時(shí)應(yīng)用程序,但繼承與多態(tài)可用與其它更多方面,每一種技術(shù)都有可以充分發(fā)揮自己能力的地方。8.6.3 繼承與多態(tài)的應(yīng)用單鏈表派生類(選讀)動(dòng)態(tài)綁定(dynamic binding)亦稱滯后綁定(late binding),對(duì)應(yīng)于靜態(tài)綁定(static binding)。如果使用對(duì)象名和點(diǎn)成員選擇運(yùn)算符“.”引用特定的一個(gè)對(duì)象來調(diào)用虛函數(shù),則被調(diào)用的虛函數(shù)是在編譯時(shí)確定的(稱為靜態(tài)綁定) 如果使用基類指針或引用指明派生類對(duì)象并使用該指針調(diào)用

38、虛函數(shù)(成員選擇符用箭頭號(hào)“-”),則程序動(dòng)態(tài)地(運(yùn)行時(shí))選擇該派生類的虛函數(shù),稱為動(dòng)態(tài)綁定。8.6.4 動(dòng)態(tài)綁定(選讀)綁定是指計(jì)算機(jī)程序自身彼此關(guān)聯(lián)的過程,是把一個(gè)標(biāo)識(shí)符名和一個(gè)存儲(chǔ)地址聯(lián)系在一起的過程,也就是把一條消息和一個(gè)對(duì)象的操作相結(jié)合的過程 。圖8.9 虛函數(shù)調(diào)用的控制流程“dog”StringObject動(dòng)態(tài)無名對(duì)象StringObject動(dòng)態(tài)無名對(duì)象“cat”指向Object類指針指向結(jié)點(diǎn)類指針指向Object類指針指向結(jié)點(diǎn)類指針指向Object類指針指向結(jié)點(diǎn)類指針StringObject動(dòng)態(tài)無名對(duì)象“cock” 析構(gòu)函數(shù)指針比較函數(shù)指針輸出函數(shù)指針StringObject虛函

39、數(shù)表抽象類Object虛函數(shù)表析構(gòu)函數(shù)指針比較函數(shù)指針輸出函數(shù)指針ComplexObject虛函數(shù) 析構(gòu)函數(shù)指針 比較函數(shù)指針 輸出函數(shù)指針 默認(rèn)析構(gòu)函數(shù)釋放動(dòng)態(tài)串析構(gòu)函數(shù)串比較函數(shù)打印串函數(shù)默認(rèn)析構(gòu)函數(shù)復(fù)數(shù)模大小比較函數(shù)打印復(fù)數(shù)函數(shù)8.6.4 動(dòng)態(tài)綁定(選讀) C+編譯器編譯含有一個(gè)或幾個(gè)虛函數(shù)的類及 其派生類時(shí),對(duì)該類建立虛函數(shù)表(Virtual function table,vtable)。 虛函數(shù)表使執(zhí)行程序正確選擇每次執(zhí)行時(shí)應(yīng)使用的虛函數(shù)。 多態(tài)是由復(fù)雜的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的,參見圖8.10。圖8.10是以【例8.10】為基礎(chǔ)的,不過增加了一個(gè)由抽象類Object派生的復(fù)數(shù)數(shù)據(jù)類Compl

40、exObject。圖中列出了基類和各派生類的虛函數(shù)表,這些表是由指向函數(shù)的指針組成的。 8.6.4 動(dòng)態(tài)綁定(選讀) 還有第二層指針,在實(shí)例化帶虛函數(shù)的類(創(chuàng)建對(duì)象)時(shí),編譯器在對(duì)象前加上一個(gè)指向該類的虛函數(shù)表的指針。 第三層指針是鏈表結(jié)點(diǎn)類對(duì)象中指向抽象基類Object的指針(這也可以是引用,但本例是指針)。 虛函數(shù)的調(diào)用是這樣進(jìn)行的,考慮虛函數(shù)Compare(),則看含“cat”的結(jié)點(diǎn)。由該結(jié)點(diǎn)的info指針找到含“cat”的無名對(duì)象,再由對(duì)象前的指針找到StringObject虛函數(shù)表,移動(dòng)4個(gè)字節(jié)(一個(gè)指針占4個(gè)字節(jié))找到比較函數(shù)指針,進(jìn)入串比較函數(shù)。UML類圖中的依賴關(guān)系依賴(dep

41、endency)依賴表示兩個(gè)元素之間存在一種關(guān)系,其中一個(gè)元素(提供者)的變化將影響另一個(gè)元素(客戶),或向它(客戶)提供所需信息。但兩者反過來是不成立的。這是將數(shù)種不同的建模關(guān)系組織到一起的簡(jiǎn)便方法。在UML的基本模型中的依賴關(guān)系在C+編程中常見的有:綁定(bind):為模板參數(shù)指定值,以生成一個(gè)新的模型元素。等效C+模板中的實(shí)例化。屬綁定依賴。訪問(access):允許某個(gè)包訪問另一個(gè)包的內(nèi)容。以下屬許可依賴。友元(friend):允許某元素訪問另一個(gè)元素,而不管被訪問者是否可見。UML類圖中的依賴關(guān)系依賴(dependency)調(diào)用(call):聲明某個(gè)類調(diào)用其他類的操作方法。以下屬使用

42、依賴。參數(shù)(parameter):一個(gè)操作和它的參數(shù)之間的關(guān)系。實(shí)例化(instantiate):這里的實(shí)例化不同于C+模板,而是泛指從概念到實(shí)體,即創(chuàng)建實(shí)例。如由類創(chuàng)建對(duì)象、由用例創(chuàng)建用例實(shí)例。創(chuàng)建實(shí)例的機(jī)制是運(yùn)行時(shí)環(huán)境的職責(zé)。發(fā)送(send):信號(hào)發(fā)送者與接受者之間的關(guān)系。另外有抽象依賴,包括跟蹤(trace)、精化(refine)、實(shí)現(xiàn)(realize)、導(dǎo)出(derive)。UML類圖中的依賴關(guān)系依賴通常用一個(gè)從客戶指向提供者的虛箭頭表示。例:下圖中類time12是12小時(shí)計(jì)時(shí),精確到分;而time24是24小時(shí)計(jì)時(shí),精確到秒??梢詫?4小時(shí)制轉(zhuǎn)換到12小時(shí)制,反之不行。類time12

43、是客戶,類time24是提供者。UML類圖中的依賴關(guān)系*綁定: 在計(jì)算機(jī)編程中,綁定是在某個(gè)時(shí)間范圍和特定的位置內(nèi)為兩個(gè)或更多編程對(duì)象或值對(duì)象創(chuàng)建聯(lián)系的過程,內(nèi)涵十分廣泛。編譯程序時(shí),綁定意味著用一個(gè)真實(shí)值替換程序中的變量值,或用來保證另一些程序和被編譯的程序一起被加載到存儲(chǔ)器中。在本C+教材中提到靜態(tài)綁定和動(dòng)態(tài)綁定是一個(gè)具體的實(shí)例,也譯作靜態(tài)聯(lián)編和動(dòng)態(tài)聯(lián)編;本教材也提到類模板和函數(shù)模板分兩步進(jìn)行編譯,其中模板實(shí)例化也是綁定的一個(gè)實(shí)例。但是在同一個(gè)地方總是要用不同的名稱來區(qū)分具體的事物,這就造成了C+和UML的術(shù)語選用的差異。綁定這個(gè)術(shù)語也用于網(wǎng)絡(luò)通信中,任何兩個(gè)網(wǎng)絡(luò)終端、實(shí)體、過程或邏輯單元

44、之間建立起一個(gè)明確的連接都可以稱為綁定。 完第八章 繼承與派生謝謝!【例8.1】由在冊(cè)人員類公有派生學(xué)生類Person:Person(string id, string name,Tsex sex,int birthday, string homeadd)IdPerson=id;Name=name;Sex=sex;Birthday=birthday;HomeAddress=homeadd; /作為一個(gè)管理程序,這個(gè)構(gòu)造函數(shù)并無必要,因?yàn)閿?shù)據(jù)總是另外輸入的。僅為說明語法存在。分析構(gòu)造函數(shù):【例8.1】由在冊(cè)人員類公有派生學(xué)生類Person:Person()IdPerson=#;Name=#;Se

45、x=mid;Birthday=0;HomeAddress=#;分析默認(rèn)的構(gòu)造函數(shù):分析析構(gòu)函數(shù):Person:Person() /string內(nèi)部動(dòng)態(tài)數(shù)組的釋放,由string自帶的析構(gòu)函數(shù)完成【例8.1】由在冊(cè)人員類公有派生學(xué)生類void Person:SetName(string name)Name=name; /拷入新姓名修改名字:void Person:SetHomeAdd(string homeadd)HomeAddress=homeadd;修改住址:【例8.1】由在冊(cè)人員類公有派生學(xué)生類void Person:PrintPersonInfo()int i;cout身份證號(hào):IdPe

46、rsonn姓名: Namen性別:;if(Sex=man)cout男n;else if(Sex=woman)cout女n; else cout n;cout出生年月日:;i=Birthday;couti/10000年;i=i%10000;couti/100月i%100日n 家庭住址:HomeAddressn;輸出個(gè)人信息:【例8.1】由在冊(cè)人員類公有派生學(xué)生類Student:Student(string id, string name,Tsex sex,int birthday, string homeadd, string nostud) :Person(id,name,sex,birthd

47、ay,homeadd) /注意Person參數(shù)名表不用類型int i;NoStudent=nostud;for(i=0;i30;i+) /課程與成績(jī)清空csi.coursename=#;csi.grade=0;派生類構(gòu)造函數(shù):【例8.1】由在冊(cè)人員類公有派生學(xué)生類Student:Student()/基類默認(rèn)的無參數(shù)構(gòu)造函數(shù)不必顯式給出int i; NoStudent=“#;for(i=0;i30;i+) /課程與成績(jī)清空,將來由鍵盤輸入 csi.coursename=“#;csi.grade=0;Student:Student() /基類析構(gòu)函數(shù)以及成員對(duì)象析構(gòu)函數(shù)自動(dòng)調(diào)用默認(rèn)派生類構(gòu)造函數(shù):

48、派生類析構(gòu)函數(shù):【例8.1】由在冊(cè)人員類公有派生學(xué)生類int Student:SetCourse(string coursename,int grade) bool b=false; /標(biāo)識(shí)新輸入的課程,還是更新成績(jī) int i; for(i=0;i30;i+) if(csi.coursename=#) /判表是否進(jìn)入未使用部分(如有對(duì)應(yīng)刪除,應(yīng)按順序表方式)csi.coursename=coursename;csi.grade=grade;b=false;break; else if(csi.coursename=coursename)/是否已有該課程記錄 csi.grade=grade;b

49、=true;break; if(i=30) return 0; /成績(jī)表滿返回0 if(b) return 1; /修改成績(jī)返回1 else return 2; /登記成績(jī)返回2學(xué)生類課程設(shè)置函數(shù):【例8.1】由在冊(cè)人員類公有派生學(xué)生類int Student:GetCourse(string coursename) int i; for(i=0;i30;i+) if(csi.coursename=coursename) return csi.grade; return -1; /找到返回成績(jī),未找到返回-1查找學(xué)生課程成績(jī)函數(shù):【例8.1】由在冊(cè)人員類公有派生學(xué)生類void Student:P

50、rintStudentInfo()int i;cout學(xué)號(hào):NoStudentn;PrintPersonInfo();for(i=0;i30;i+) /打印各科成績(jī)if(csi.coursename!=#) coutcsi.coursename tcsi.graden;else break;cout-完- endl;打印學(xué)生情況函數(shù):例8.1驗(yàn)證用主函數(shù):int main(void) char temp30; int i,k; Person per1(320102820818161,沈俊, man,19820818,南京四牌樓2號(hào)); Person per2; per2.SetName(朱明)

51、; per2.SetSex(woman); per2.SetBirth(19780528); per2.SetId(320102780528162); per2.SetHomeAdd(南京市成賢街9號(hào)); per1.PrintPersonInfo(); per2.PrintPersonInfo(); Student stu1(320102811226161,朱海鵬, man,19811226,南京市黃浦路1號(hào),06000123); cout請(qǐng)輸入各科成績(jī):temp; /輸入格式:物理 80 if(!strcmp(temp,end) break; cink; i=stu1.SetCourse(t

52、emp,k); if(i=0) cout成績(jī)列表已滿!n; else if(i=1) cout修改成績(jī)n; else cout登記成績(jī)n; stu1.PrintStudentInfo(); while(1) cout查詢成績(jī)n請(qǐng)輸入科目:temp; if(!strcmp(temp,end) break; k=stu1.GetCourse(temp); if(k=-1) cout未查到n; else coutkn; return 0;【例8.2】由圓和高多重繼承派生出圓錐class Circleprotected: float x,y,r; /(x,y)為圓心,r為半徑public: Circl

53、e(float a=0,float b=0,float R=0)x=a;y=b;r=R; void Setcoordinate(float a,float b)x=a;y=b; /設(shè)置圓心坐標(biāo) void Getcoordinate(float &a,float &b)a=x;b=y; void SetR(float R)r=R;/設(shè)置半徑 float GetR()return r;/取圓半徑 float GetAreaCircle()return float(r*r*3.14159); /取圓面積 float GetCircumference()return float(2*r*3.14159

54、); /取圓周長(zhǎng);高類Line:【例8.2】由圓和高多重繼承派生出圓錐class Lineprotected: float High;public: Line(float a=0)High=a; void SetHigh(float a)High=a; float GetHigh()return High;class Cone:public Circle,public Linepublic: Cone(float a,float b,float R,float d):Circle(a,b,R),Line(d) float GetCV()return float(GetAreaCircle()*

55、High/3); /取得圓錐體積 float GetCA() /取得圓錐表面積 return float(GetAreaCircle()+r*3.14159*sqrt(r*r+High*Hgih); /共有派生類中能直接訪問直接基類的保護(hù)成員【例8.2】由圓和高多重繼承派生出圓錐派生類圓錐:在VC+平臺(tái)上運(yùn)行例8.2int main()Cone c1(5,8,3,4);float a,b;cout圓錐體積:c1.GetCV()n;cout圓錐表面積:c1.GetCA()n;cout圓錐底面積:c1.GetAreaCircle()n;cout圓錐底周長(zhǎng):c1.GetCircumference()

56、n;cout圓錐底半徑:c1.GetR()n;c1.Getcoordinate(a,b);cout圓錐底圓心坐標(biāo):(a,b)n;cout圓錐高:c1.GetHigh()n;return 0;【例8.2】由圓和高多重繼承派生出圓錐檢證主程序:class Student:public virtual Personstring NoStudent; /學(xué)號(hào)/30門課程與成績(jī)略public:Student(string id, string name,Tsex sex,int birthday, string homeadd, string nostud);Student(); Student()co

57、ut析構(gòu)Studentendl;void PrintStudentInfo(); ;Student:Student(string id, string name,Tsex sex, int birthday, string homeadd, string nostud) :Person(id,name,sex,birthday,homeadd) /注意Person參數(shù)名表不用類型cout構(gòu)造Studentendl;NoStudent=nostud;例8.4 虛基類與在職研究生以虛基類定義公有派生的學(xué)生類:Student:Student() /基類默認(rèn)的無參數(shù)構(gòu)造函數(shù)不必顯式給出cout構(gòu)造St

58、udentendl;void Student:PrintStudentInfo()cout學(xué)號(hào):NoStudentn;PrintPersonInfo();例8.4 虛基類與在職研究生以虛基類定義公有派生的學(xué)生類:class GStudent:public Student /以虛基類定義公有派生的研究生類 string NoGStudent; /研究生號(hào),其他略public: GStudent(string id, string name,Tsex sex,int birthday, string homeadd, string nostud,string nogstudent); /注意派生類

59、構(gòu)造函數(shù)聲明方式 GStudent(); GStudent()cout析構(gòu)GStudentendl; void PrintGStudentInfo();GStudent:GStudent(string id, string name,Tsex sex,int birthday, string homeadd, string nostud, string nogstud): Student(id,name,sex,birthday,homeadd,nostud), Person(id,name,sex,birthday,homeadd) /因Person是虛基類,盡管不是直接基類, Person

60、必須出現(xiàn)。 /不定義對(duì)象可不出現(xiàn),為通用應(yīng)出現(xiàn)。如不是虛基類,出現(xiàn)是錯(cuò)誤的 cout構(gòu)造GStudentendl; NoGStudent=nogstud;例8.4 虛基類與在職研究生以虛基類定義公有派生的研究生類:GStudent:GStudent() /基類默認(rèn)的無參數(shù)構(gòu)造函數(shù)不必顯式給出cout構(gòu)造GStudentendl;void GStudent:PrintGStudentInfo()cout研究生號(hào):NoGStudentn;PrintStudentInfo();例8.4 虛基類與在職研究生以虛基類定義公有派生的研究生類:例8.4 虛基類與在職研究生class Employee:pub

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論