類的繼承和派生_第1頁
類的繼承和派生_第2頁
類的繼承和派生_第3頁
類的繼承和派生_第4頁
類的繼承和派生_第5頁
已閱讀5頁,還剩106頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、學(xué)校在學(xué)校在冊(cè)人員冊(cè)人員 學(xué)生學(xué)生 教職工教職工第八章第八章 繼承與多態(tài)繼承與多態(tài)本科生本科生研究生研究生碩士生碩士生博士生博士生教師教師 行政行政 人員人員 工人工人【例例8.18.1】由在冊(cè)人員類公有派生學(xué)生類由在冊(cè)人員類公有派生學(xué)生類class Personstring IdPerson;/身份證號(hào)身份證號(hào),18位數(shù)字位數(shù)字string Name;/姓名姓名bool Sex; /性別性別int Birthday;/格式格式1986年年8月月18日寫作日寫作19860818string HomeAddress;/家庭地址家庭地址public:Person(string, string, T

2、sex, int, string); /構(gòu)造函數(shù)構(gòu)造函數(shù) Person(); /默認(rèn)的構(gòu)造函數(shù)默認(rèn)的構(gòu)造函數(shù) Person(); /析構(gòu)函數(shù)析構(gòu)函數(shù)【例例8.18.1】由在冊(cè)人員類公有派生學(xué)生類由在冊(cè)人員類公有派生學(xué)生類 void SetName(string); /修改名字修改名字 string GetName()return Name; /提取名字提取名字 void SetSex(Tsex sex)Sex=sex; /修改性別修改性別 bool GetSex()return Sex;/提取性別提取性別 void SetId(string id)IdPerson=id;/修改身份證號(hào)修改身份

3、證號(hào) string GetId()return IdPerson; /提取身份證號(hào)提取身份證號(hào) void SetBirth(int birthday)Birthday=birthday; /修改生日修改生日 int GetBirth()return Birthday; /提取生日提取生日 void SetHomeAdd(string ); /修改住址修改住址 string GetHomeAdd()return HomeAddress; /提取住址提取住址 void PrintInfo(); /打印個(gè)人信息打印個(gè)人信息;/接口函數(shù):接口函數(shù):繼承繼承(inheritance)(inheritan

4、ce):該機(jī)制是面向?qū)ο蟪绦蛟O(shè)計(jì)使代碼可以復(fù)用的最重要的手該機(jī)制是面向?qū)ο蟪绦蛟O(shè)計(jì)使代碼可以復(fù)用的最重要的手段,它允許程序員在保持原有類特性的基礎(chǔ)上進(jìn)行擴(kuò)展,段,它允許程序員在保持原有類特性的基礎(chǔ)上進(jìn)行擴(kuò)展,增加功能。增加功能。這樣產(chǎn)生新的類,稱派生類。繼承呈現(xiàn)了面向這樣產(chǎn)生新的類,稱派生類。繼承呈現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計(jì)的層次結(jié)構(gòu)。對(duì)象程序設(shè)計(jì)的層次結(jié)構(gòu)。體現(xiàn)了由簡(jiǎn)單到復(fù)雜的認(rèn)識(shí)過體現(xiàn)了由簡(jiǎn)單到復(fù)雜的認(rèn)識(shí)過程程。第八章第八章 繼承與多態(tài)繼承與多態(tài)多態(tài)性多態(tài)性(polymorphism):(polymorphism):多態(tài)性是考慮在不同層次的類中,以及在同一類中,同名多態(tài)性是考慮在不同層次的類中,

5、以及在同一類中,同名的成員函數(shù)之間的關(guān)系問題。函數(shù)的重載,運(yùn)算符的重載,的成員函數(shù)之間的關(guān)系問題。函數(shù)的重載,運(yùn)算符的重載,屬于編譯時(shí)的多態(tài)性。以虛函數(shù)為基礎(chǔ)的運(yùn)行時(shí)的多態(tài)性屬于編譯時(shí)的多態(tài)性。以虛函數(shù)為基礎(chǔ)的運(yùn)行時(shí)的多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的標(biāo)志性特征。是面向?qū)ο蟪绦蛟O(shè)計(jì)的標(biāo)志性特征。 體現(xiàn)了類推和比喻的體現(xiàn)了類推和比喻的思想方法。思想方法。 【例例8.18.1】由在冊(cè)人員類公有派生學(xué)生類由在冊(cè)人員類公有派生學(xué)生類class Personstring IdPerson;/身份證號(hào)身份證號(hào),18位數(shù)字位數(shù)字string Name;/姓名姓名bool Sex; /性別性別int Birthday

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

7、; /修改性別修改性別 Tsex GetSex()return Sex;/提取性別提取性別 void SetId(string id)IdPerson=id;/修改身份證號(hào)修改身份證號(hào) string GetId()return IdPerson; /提取身份證號(hào)提取身份證號(hào) void SetBirth(int birthday)Birthday=birthday; /修改生日修改生日 int GetBirth()return Birthday; /提取生日提取生日 void SetHomeAdd(string ); /修改住址修改住址 string GetHomeAdd()return Hom

8、eAddress; /提取住址提取住址 virtual void PrintInfo(); /打印個(gè)人信息打印個(gè)人信息;/接口函數(shù):接口函數(shù):【例例8.18.1】由在冊(cè)人員類公有派生學(xué)生類由在冊(cè)人員類公有派生學(xué)生類派生的學(xué)生類派生的學(xué)生類: :class Student: public Person/定義派生的學(xué)生類定義派生的學(xué)生類 string NoStudent; /學(xué)號(hào)學(xué)號(hào) course cs30; /30門課程與成績(jī)門課程與成績(jī)public: Student(string id, string name,Tsex sex,int birthday, string homeadd, st

9、ring nostud);/注意注意派生類構(gòu)造函數(shù)派生類構(gòu)造函數(shù)聲明方式聲明方式 Student();/默認(rèn)派生類構(gòu)造函數(shù)默認(rèn)派生類構(gòu)造函數(shù) Student();/派生類析構(gòu)函數(shù)派生類析構(gòu)函數(shù) SetCourse(string , int); /課程設(shè)置課程設(shè)置 int GetCourse(string ); /查找成績(jī)查找成績(jī) void PrintInfo(); /打印學(xué)生情況打印學(xué)生情況;struct course string coursename; int grade;第八章 繼承與多態(tài)8.1 繼承與派生的概念繼承與派生的概念 8.4 虛基類虛基類 (選讀)(選讀) 8.3 多重繼承與

10、派生類成員標(biāo)識(shí)多重繼承與派生類成員標(biāo)識(shí) 8. 6 多態(tài)性與虛函數(shù)多態(tài)性與虛函數(shù) 8.5 派生類應(yīng)用討論派生類應(yīng)用討論 8.2 派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù) 8.1 繼承與派生的概念層次概念層次概念是計(jì)算機(jī)的重要概念。通過是計(jì)算機(jī)的重要概念。通過繼承繼承(inheritance)的機(jī)制可對(duì)類(的機(jī)制可對(duì)類(class)分層,提供類型)分層,提供類型/子類型的關(guān)系。子類型的關(guān)系。 C+通過通過類派生類派生(class derivation)的機(jī)制來支持繼承。)的機(jī)制來支持繼承。被繼承的類稱為被繼承的類稱為基類基類(base class)或)或超類超類(superclass)

11、,),新的類為新的類為派生類派生類(derived class)或)或子類子類(subclass)。)。 基基類和派生類的集合稱作類和派生類的集合稱作類繼承層次結(jié)構(gòu)類繼承層次結(jié)構(gòu)(hierarchy)。)。 如果基類和派生類共享相同的公有接口,則派生類被稱作如果基類和派生類共享相同的公有接口,則派生類被稱作基類的子類型(基類的子類型(subtype)。)。 層次概念:層次概念:派生反映了事物之間的聯(lián)系,事物的共性與個(gè)性之間的關(guān)系。派生反映了事物之間的聯(lián)系,事物的共性與個(gè)性之間的關(guān)系。 派生與獨(dú)立設(shè)計(jì)若干相關(guān)的類,前者工作量少,重復(fù)的部分派生與獨(dú)立設(shè)計(jì)若干相關(guān)的類,前者工作量少,重復(fù)的部分可以從

12、基類繼承來,不需要單獨(dú)可以從基類繼承來,不需要單獨(dú)編程編程。 8.1 繼承與派生的概念8.1.1 類的派生與繼承類的派生與繼承 8. 1.2 公有派生與私有派生公有派生與私有派生 【例例8.18.1】由在冊(cè)人員類公有派生學(xué)生類由在冊(cè)人員類公有派生學(xué)生類派生的學(xué)生類派生的學(xué)生類: :class Student: public Person/定義派生的學(xué)生類定義派生的學(xué)生類 string NoStudent; /學(xué)號(hào)學(xué)號(hào) course cs30; /30門課程與成績(jī)門課程與成績(jī)public: Student(string id, string name,Tsex sex,int birthday,

13、 string homeadd, string nostud);/注意派生類構(gòu)造函數(shù)聲明方式注意派生類構(gòu)造函數(shù)聲明方式 Student();/默認(rèn)派生類構(gòu)造函數(shù)默認(rèn)派生類構(gòu)造函數(shù) Student();/派生類析構(gòu)函數(shù)派生類析構(gòu)函數(shù) SetCourse(string , int); /課程設(shè)置課程設(shè)置 int GetCourse(string ); /查找成績(jī)查找成績(jī) void PrintInfo(); /打印學(xué)生情況打印學(xué)生情況;struct course string coursename; int grade;派生類的定義:派生類的定義:class 派生類名:訪問限定符派生類名:訪問限定符

14、 基類名基類名1,訪問限定符,訪問限定符 基類名基類名2,訪問限定符,訪問限定符 基類名基類名n private: 成員表成員表1; /派生類增加或替代的私有成員派生類增加或替代的私有成員public:成員表成員表2; /派生類增加或替代的公有成員派生類增加或替代的公有成員protected:成員表成員表3; /派生類增加或替代的保護(hù)成員派生類增加或替代的保護(hù)成員;/分號(hào)不可少分號(hào)不可少其中基類其中基類1 1,基類,基類2 2,是已聲明的類。是已聲明的類。 在派生類定義的類體中在派生類定義的類體中給出的成員稱為給出的成員稱為派生類成員派生類成員,它們是新增加成員,它們給派生類,它們是新增加成員

15、,它們給派生類添加了不同于基類的新的屬性和功能。派生類成員也包括取代基添加了不同于基類的新的屬性和功能。派生類成員也包括取代基類成員的更新成員。類成員的更新成員。8.1.1 8.1.1 類的派生與繼承類的派生與繼承基類基類1基類基類2基類基類n派生類派生類1派生類派生類2基類基類派生類派生類1派生類派生類2(a)多重繼承)多重繼承 (b)單繼承)單繼承 圖圖8.1 多重繼承與單繼承多重繼承與單繼承 一個(gè)基類一個(gè)基類可以直接可以直接派生出多派生出多個(gè)派生類個(gè)派生類 派生類可派生類可以由多個(gè)以由多個(gè)基類共同基類共同派生出來,派生出來,稱多重繼稱多重繼承。承。8.1.1 8.1.1 類的派生與繼承類

16、的派生與繼承多重繼承:多重繼承:如果一個(gè)派生類可以同時(shí)有多個(gè)基類,稱如果一個(gè)派生類可以同時(shí)有多個(gè)基類,稱為多重繼承(為多重繼承(multiple-inheritance),這時(shí)的派生類同),這時(shí)的派生類同時(shí)得到了多個(gè)已有類的特征。時(shí)得到了多個(gè)已有類的特征。單繼承:?jiǎn)卫^承:派生類只有一個(gè)直接基類的情況稱為單繼承派生類只有一個(gè)直接基類的情況稱為單繼承(single-inheritance)。)。8.1.1 8.1.1 類的派生與繼承類的派生與繼承 在派生過程中,派生出來的新類同樣可以在派生過程中,派生出來的新類同樣可以作為基類再繼續(xù)派生出更新的類,依此類推形作為基類再繼續(xù)派生出更新的類,依此類推形

17、成一個(gè)層次結(jié)構(gòu)。直接參與派生出某類稱為直成一個(gè)層次結(jié)構(gòu)。直接參與派生出某類稱為直接基類,而基類的基類,以及更深層的基類稱接基類,而基類的基類,以及更深層的基類稱為為間接基類間接基類。類族:類族: 同時(shí)一個(gè)基類可以直接派生出多個(gè)派生類。同時(shí)一個(gè)基類可以直接派生出多個(gè)派生類。這樣形成了一個(gè)相互關(guān)聯(lián)的類族。如這樣形成了一個(gè)相互關(guān)聯(lián)的類族。如MFC就是就是這樣的族類,它由一個(gè)這樣的族類,它由一個(gè)CObject類派生出類派生出200個(gè)個(gè)MFC類中的絕大多數(shù)。類中的絕大多數(shù)。 多層次繼承:多層次繼承:編制編制派生派生類時(shí)類時(shí)可分可分四步四步 吸收基類的成員吸收基類的成員 改造基類成員改造基類成員 發(fā)展新成

18、員發(fā)展新成員 重寫構(gòu)造函數(shù)與析構(gòu)函數(shù)重寫構(gòu)造函數(shù)與析構(gòu)函數(shù) 8.1.1 8.1.1 類的派生與繼承類的派生與繼承不論是數(shù)據(jù)成員,還是函數(shù)成員,不論是數(shù)據(jù)成員,還是函數(shù)成員,除構(gòu)造函數(shù)與析構(gòu)函數(shù)外全盤接收除構(gòu)造函數(shù)與析構(gòu)函數(shù)外全盤接收 聲明一個(gè)和某基類成員同名的新成員聲明一個(gè)和某基類成員同名的新成員,派派生類中的新成員就屏蔽了基類同名成員生類中的新成員就屏蔽了基類同名成員稱為稱為同名覆蓋同名覆蓋(override) 派生類新成員必須與基類成員不同名,它派生類新成員必須與基類成員不同名,它的加入保證派生類在功能上有所發(fā)展。的加入保證派生類在功能上有所發(fā)展。 派生編程步驟:派生編程步驟:8.1.1

19、8.1.1 類的派生與繼承類的派生與繼承第二步中,第二步中,新成員如是成員函數(shù),參數(shù)表也必須一樣新成員如是成員函數(shù),參數(shù)表也必須一樣,否,否則是重載。則是重載。第三步中,獨(dú)有的新成員才是繼承與派生的核心特征。第三步中,獨(dú)有的新成員才是繼承與派生的核心特征。第四步是重寫構(gòu)造函數(shù)與析構(gòu)函數(shù),派生類不繼承這兩種第四步是重寫構(gòu)造函數(shù)與析構(gòu)函數(shù),派生類不繼承這兩種函數(shù)。不管原來的函數(shù)是否可用函數(shù)。不管原來的函數(shù)是否可用一律重寫可免出錯(cuò)一律重寫可免出錯(cuò)(?)。訪問控制:訪問控制:亦稱為亦稱為繼承方式繼承方式,是對(duì)基類成員進(jìn)一步的限制。訪問控制,是對(duì)基類成員進(jìn)一步的限制。訪問控制也是三種:也是三種:公有(公

20、有(public)方式,亦稱公有繼承)方式,亦稱公有繼承保護(hù)(保護(hù)(protected)方式,亦稱保護(hù)繼承)方式,亦稱保護(hù)繼承私有(私有(private)方式,)方式, 亦稱私有繼承。亦稱私有繼承。 8.1.2 8.1.2 公有派生與私有派生公有派生與私有派生訪問限定符兩方面含義:訪問限定符兩方面含義:派生類成員(新增成員)函數(shù)派生類成員(新增成員)函數(shù)對(duì)基類(繼承來的)成員的訪問(調(diào)用和操作)對(duì)基類(繼承來的)成員的訪問(調(diào)用和操作),和,和從從派生類對(duì)象之外對(duì)派生類對(duì)象中的基類成員的訪問派生類對(duì)象之外對(duì)派生類對(duì)象中的基類成員的訪問。class Student: public Person

21、public: Student(string id, string name,Tsex sex,int birthday, string homeadd, string nostud);class Person private:string Name;/姓名姓名public:string GetName()return Name; /提取名字提取名字8.1.2 8.1.2 公有派生與私有派生公有派生與私有派生不可直接訪問 不可直接訪問 private 不可直接訪問 private protected 不可直接訪問 private public 私有派生 不可直接訪問 不可直接訪問 privat

22、e 不可直接訪問 protected protected 可直接訪問 public public 公有派生 在派生類對(duì)象外訪問派生類對(duì)象的基類成員 在派生類中對(duì)基類成員的訪問限定 基類中的訪問限定 派生方式 公有派生是絕對(duì)主流公有派生是絕對(duì)主流。 【例例8.18.1】由在冊(cè)人員類公有派生學(xué)生類由在冊(cè)人員類公有派生學(xué)生類/注意注意Person參數(shù)表不用類型參數(shù)表不用類型Student:Student (string id, string name, Tsex sex, int birthday, string homeadd, string nostud) : Person(id, name,

23、sex, birthday, homeadd) NoStudent = nostud;for( int i=0; i30; i+) /課程與成績(jī)清空課程與成績(jī)清空 csi.coursename = #;csi.grade = 0;派生類構(gòu)造函數(shù)派生類構(gòu)造函數(shù):派生類構(gòu)造函數(shù)的定義:派生類構(gòu)造函數(shù)的定義:派生類名派生類名:派生類名(參數(shù)總表)派生類名(參數(shù)總表):基類名基類名1(參數(shù)名表(參數(shù)名表1),基類名,基類名2(參數(shù)名表(參數(shù)名表2),),基類名,基類名n(參數(shù)名表(參數(shù)名表n),成員對(duì)象名成員對(duì)象名1(成員對(duì)象參數(shù)名表(成員對(duì)象參數(shù)名表1),),成,成員對(duì)象名員對(duì)象名m(成員對(duì)象參數(shù)名

24、表(成員對(duì)象參數(shù)名表m) /派生類新增成員的初始化;派生類新增成員的初始化; /所列出的成員對(duì)象名全部為新增成員對(duì)象的名字所列出的成員對(duì)象名全部為新增成員對(duì)象的名字注意:注意: 在構(gòu)造函數(shù)的聲明中,冒號(hào)及冒號(hào)以后部分必須略去。在構(gòu)造函數(shù)的聲明中,冒號(hào)及冒號(hào)以后部分必須略去。 所謂不能繼承并不是不能利用,而是把基類的構(gòu)造函數(shù)作所謂不能繼承并不是不能利用,而是把基類的構(gòu)造函數(shù)作為新的構(gòu)造函數(shù)的一部分,或者講調(diào)用基類的構(gòu)造函數(shù)。為新的構(gòu)造函數(shù)的一部分,或者講調(diào)用基類的構(gòu)造函數(shù)。基基類名僅指直接基類,寫了底層基類,編譯器認(rèn)為出錯(cuò)類名僅指直接基類,寫了底層基類,編譯器認(rèn)為出錯(cuò)。 冒號(hào)后的基類名,成員對(duì)象

25、名的次序可以隨意,這里的次冒號(hào)后的基類名,成員對(duì)象名的次序可以隨意,這里的次序與調(diào)用次序無關(guān)。序與調(diào)用次序無關(guān)。 8.2 8.2 派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)派生類構(gòu)造函數(shù)各部分執(zhí)行次序:派生類構(gòu)造函數(shù)各部分執(zhí)行次序: 1.1.調(diào)用基類構(gòu)造函數(shù),按它們?cè)谂缮惗x調(diào)用基類構(gòu)造函數(shù),按它們?cè)谂缮惗x的先后順序,順序調(diào)用。的先后順序,順序調(diào)用。 2.2.調(diào)用成員對(duì)象的構(gòu)造函數(shù),按它們?cè)陬惗ㄕ{(diào)用成員對(duì)象的構(gòu)造函數(shù),按它們?cè)陬惗x中聲明的先后順序,順序調(diào)用。義中聲明的先后順序,順序調(diào)用。3.3.派生類的構(gòu)造函數(shù)體中的操作。派生類的構(gòu)造函數(shù)體中的操作。8.2 8.2 派生類的構(gòu)

26、造函數(shù)與析構(gòu)函數(shù)派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)注意:注意: 在派生類構(gòu)造函數(shù)中,只要基類不是使用無參的默認(rèn)在派生類構(gòu)造函數(shù)中,只要基類不是使用無參的默認(rèn)構(gòu)造函數(shù)都要顯式給出基類名和參數(shù)表構(gòu)造函數(shù)都要顯式給出基類名和參數(shù)表。 如果基類沒有定義構(gòu)造函數(shù),則派生類也可以不定義,如果基類沒有定義構(gòu)造函數(shù),則派生類也可以不定義,全部采用系統(tǒng)給定的默認(rèn)構(gòu)造函數(shù)。全部采用系統(tǒng)給定的默認(rèn)構(gòu)造函數(shù)。 如果基類定義了帶有形參表的構(gòu)造函數(shù)時(shí),派生類就如果基類定義了帶有形參表的構(gòu)造函數(shù)時(shí),派生類就應(yīng)當(dāng)定義構(gòu)造函數(shù)。應(yīng)當(dāng)定義構(gòu)造函數(shù)。8.2 8.2 派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)析構(gòu)函數(shù):析構(gòu)函數(shù):析

27、構(gòu)函數(shù)析構(gòu)函數(shù)的功能是作善后工作。的功能是作善后工作。 只要在函數(shù)體內(nèi)把派生類新增一般成員處理好只要在函數(shù)體內(nèi)把派生類新增一般成員處理好就可以了就可以了,而,而對(duì)新增的成員對(duì)象和基類的善后工作,對(duì)新增的成員對(duì)象和基類的善后工作,系統(tǒng)會(huì)自己調(diào)用成員對(duì)象和基類的析構(gòu)函數(shù)來完成系統(tǒng)會(huì)自己調(diào)用成員對(duì)象和基類的析構(gòu)函數(shù)來完成。 析構(gòu)函數(shù)各部分執(zhí)行次序與構(gòu)造函數(shù)相反,析構(gòu)函數(shù)各部分執(zhí)行次序與構(gòu)造函數(shù)相反,首首先對(duì)派生類新增一般成員析構(gòu),然后對(duì)新增對(duì)象成先對(duì)派生類新增一般成員析構(gòu),然后對(duì)新增對(duì)象成員析構(gòu),最后對(duì)基類成員析構(gòu)員析構(gòu),最后對(duì)基類成員析構(gòu)?!纠?.18.1】由在冊(cè)人員類公有派生學(xué)生類由在冊(cè)人員類

28、公有派生學(xué)生類【例例8.1】由在冊(cè)人員類公有派生學(xué)生類。我們希望基類和派生類由在冊(cè)人員類公有派生學(xué)生類。我們希望基類和派生類共享相同的公有接口共享相同的公有接口,只能采用公有派生來實(shí)現(xiàn)。只能采用公有派生來實(shí)現(xiàn)?;悾夯悾篹num Tsex mid, man, woman ; class Personstring IdPerson;/身份證號(hào)身份證號(hào),18位數(shù)字位數(shù)字string Name;/姓名姓名Tsex Sex; /性別性別int Birthday;/格式格式1986年年8月月18日寫作日寫作19860818string HomeAddress;/家庭地址家庭地址public:Perso

29、n(string, string,Tsex,int, string);/構(gòu)造函數(shù)構(gòu)造函數(shù) Person(); /默認(rèn)的構(gòu)造函數(shù)默認(rèn)的構(gòu)造函數(shù) Person(); /析構(gòu)函數(shù)析構(gòu)函數(shù)【例例8.18.1】由在冊(cè)人員類公有派生學(xué)生類由在冊(cè)人員類公有派生學(xué)生類void SetName(string); /修改名字修改名字string GetName()return Name; /提取名字提取名字void SetSex(Tsex sex)Sex=sex; /修改性別修改性別Tsex GetSex()return Sex;/提取性別提取性別void SetId(string id)IdPerson=id;

30、/修改身份證號(hào)修改身份證號(hào)string GetId()return IdPerson; /提取身份證號(hào)提取身份證號(hào)void SetBirth(int birthday)Birthday=birthday; /修改生日修改生日int GetBirth()return Birthday; /提取生日提取生日void SetHomeAdd(string ); /修改住址修改住址string GetHomeAdd()return HomeAddress; /提取住址提取住址virtual void PrintInfo(); /輸出個(gè)人信息輸出個(gè)人信息 ;/接口函數(shù):接口函數(shù):【例例8.18.1】由在冊(cè)

31、人員類公有派生學(xué)生類由在冊(cè)人員類公有派生學(xué)生類派生的學(xué)生類派生的學(xué)生類: :class Student: public Person/定義派生的學(xué)生類定義派生的學(xué)生類 string NoStudent; /學(xué)號(hào)學(xué)號(hào) course cs30; /30門課程與成績(jī)門課程與成績(jī)public: Student(string id, string name,Tsex sex,int birthday, string homeadd, string nostud);/注意注意派生類構(gòu)造函數(shù)派生類構(gòu)造函數(shù)聲明方式聲明方式 Student();/默認(rèn)派生類構(gòu)造函數(shù)默認(rèn)派生類構(gòu)造函數(shù) Student();/派生

32、類析構(gòu)函數(shù)派生類析構(gòu)函數(shù) SetCourse(string , int); /課程設(shè)置課程設(shè)置 int GetCourse(string ); /查找成績(jī)查找成績(jī) void PrintInfo(); /打印學(xué)生情況打印學(xué)生情況;struct course string coursename; int grade;驗(yàn)證驗(yàn)證主函數(shù)主函數(shù)8.2 8.2 派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)注意:注意: 本例中標(biāo)準(zhǔn)本例中標(biāo)準(zhǔn)C+字符串字符串string是作為成員對(duì)象使用的是作為成員對(duì)象使用的(聚合聚合),動(dòng)態(tài)內(nèi)存分配的構(gòu)造和析構(gòu)被封裝起來,使用十),動(dòng)態(tài)內(nèi)存分配的構(gòu)造和析構(gòu)被封裝起來,

33、使用十分簡(jiǎn)單。如使用動(dòng)態(tài)生成的分簡(jiǎn)單。如使用動(dòng)態(tài)生成的C風(fēng)格字符串,要考慮深復(fù)制,風(fēng)格字符串,要考慮深復(fù)制,那要復(fù)雜得多。那要復(fù)雜得多。 提倡完善的類對(duì)象封裝,不僅封裝數(shù)據(jù)和對(duì)數(shù)據(jù)的操作,提倡完善的類對(duì)象封裝,不僅封裝數(shù)據(jù)和對(duì)數(shù)據(jù)的操作,而且封裝資源的動(dòng)態(tài)分配與釋放,形成一個(gè)完備的子系統(tǒng)。而且封裝資源的動(dòng)態(tài)分配與釋放,形成一個(gè)完備的子系統(tǒng)。在一個(gè)有層次結(jié)構(gòu)的類體系中資源的動(dòng)態(tài)分配與釋放應(yīng)封裝在一個(gè)有層次結(jié)構(gòu)的類體系中資源的動(dòng)態(tài)分配與釋放應(yīng)封裝在成員對(duì)象中在成員對(duì)象中,如同使用標(biāo)準(zhǔn)的,如同使用標(biāo)準(zhǔn)的string字符串類那樣。字符串類那樣。 聚合是一種完善的封裝。采用成員對(duì)象將大大簡(jiǎn)化層次聚合是一

34、種完善的封裝。采用成員對(duì)象將大大簡(jiǎn)化層次結(jié)構(gòu)的類體系中資源的動(dòng)態(tài)分配與釋放的處理方法,不再出結(jié)構(gòu)的類體系中資源的動(dòng)態(tài)分配與釋放的處理方法,不再出現(xiàn)難度極大的多層次的深復(fù)制?,F(xiàn)難度極大的多層次的深復(fù)制。8.3 8.3 多重繼承與派生類成員標(biāo)識(shí)(選讀)多重繼承與派生類成員標(biāo)識(shí)(選讀)由多個(gè)基類共同派生出新的派生類,這樣的繼承結(jié)構(gòu)由多個(gè)基類共同派生出新的派生類,這樣的繼承結(jié)構(gòu)被稱為多重繼承或多繼承(被稱為多重繼承或多繼承(multiple-inheritance) 椅子椅子床床沙發(fā)沙發(fā)(單繼承單繼承)躺椅躺椅(多重繼承多重繼承)兩用沙發(fā)兩用沙發(fā)(多重繼承多重繼承)圖圖8.2 椅子,床到兩用沙發(fā)椅子,

35、床到兩用沙發(fā)多重繼承實(shí)例:多重繼承實(shí)例:在冊(cè)人員在冊(cè)人員學(xué)生學(xué)生(單繼承單繼承)教職工教職工(單繼承單繼承)兼職教師兼職教師(單繼承單繼承)教師教師(單繼承單繼承)行政人員行政人員(單繼承單繼承)工人工人(單繼承單繼承)研究生研究生(單繼承單繼承)行政人員兼教師行政人員兼教師(多重繼承多重繼承)在職研究生在職研究生(多重繼承多重繼承)研究生助教研究生助教(多重繼承多重繼承)圖圖8.3 大學(xué)在冊(cè)人員繼承關(guān)系大學(xué)在冊(cè)人員繼承關(guān)系8.3 8.3 多重繼承與派生類成員標(biāo)識(shí)(選讀)多重繼承與派生類成員標(biāo)識(shí)(選讀)派生出來派生出來的新類同的新類同樣可以作樣可以作為基類再為基類再繼續(xù)派生繼續(xù)派生出更新的出更

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

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

38、 int No身份證號(hào) .class Employee int No工作證號(hào) .class Person int No身份證號(hào) .圖圖8.4(a)在職研究生派生類關(guān)系)在職研究生派生類關(guān)系 定義定義EGStudent類對(duì)象類對(duì)象EGStudent1,并假定派生全部為公有派生,并假定派生全部為公有派生,而而int No全為公有成員全為公有成員:EGStud1.No /在職學(xué)號(hào)在職學(xué)號(hào)EGStud1.GStudent:No /研究生號(hào)研究生號(hào)EGStud1.GStudent.Student:No /學(xué)生號(hào)學(xué)生號(hào) EGStud1.GStudent.Student. Person:No /身份證號(hào)身份

39、證號(hào)EGStud1.Employee:No /工作證號(hào)工作證號(hào)EGStud1.Employee.Person:No /身份證號(hào)身份證號(hào)兩個(gè)身份證號(hào)從邏輯上兩個(gè)身份證號(hào)從邏輯上講應(yīng)是一回事講應(yīng)是一回事,但是物理但是物理上是分配了不同內(nèi)存空上是分配了不同內(nèi)存空間,是兩個(gè)變量,請(qǐng)參間,是兩個(gè)變量,請(qǐng)參見圖見圖8.4(b)。Person Person StudentEmployee GStudent EGStudentPerson成員成員 Person成員成員 Student新成員新成員 GStudent新成員新成員 Employee新成員新成員 EGStudent新成員新成員 圖圖8.4(b)在職研

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

41、學(xué)生號(hào)EGStud1.GStudent:Student:Person:No /身份證號(hào)身份證號(hào)是是錯(cuò)誤錯(cuò)誤的。的。 8.3 8.3 多重繼承與派生類成員標(biāo)識(shí)(選讀)多重繼承與派生類成員標(biāo)識(shí)(選讀)8.3 8.3 多重繼承與派生類成員標(biāo)識(shí)(選讀)多重繼承與派生類成員標(biāo)識(shí)(選讀)一般數(shù)據(jù)成員總是私有成員,派生類對(duì)基類一般數(shù)據(jù)成員總是私有成員,派生類對(duì)基類的訪問只能間接進(jìn)行。訪問身份證號(hào),應(yīng)通的訪問只能間接進(jìn)行。訪問身份證號(hào),應(yīng)通過過class Personclass Person中的公有成員函數(shù)(接口)中的公有成員函數(shù)(接口)GetNoGetNo()()和和SetNoSetNo()()進(jìn)行:進(jìn)行:

42、EGStud1.Employee.Person:SetNo(int no);no=EGStud1.Employee.Person:GetNo();注意:注意:【例例8.2】由圓和高多重繼承派生出圓錐。由圓和高多重繼承派生出圓錐。 因?yàn)楣信缮鷷r(shí),在派生類中不可以直接訪問基類的私有因?yàn)楣信缮鷷r(shí),在派生類中不可以直接訪問基類的私有成員,但成員,但可以直接訪問基類的保護(hù)成員可以直接訪問基類的保護(hù)成員,當(dāng)需要在派生類中訪問,當(dāng)需要在派生類中訪問基類的數(shù)據(jù)成員時(shí),可以將它們定義為保護(hù)的,而不是私有的。基類的數(shù)據(jù)成員時(shí),可以將它們定義為保護(hù)的,而不是私有的。 本例中類本例中類Circle為圓;類為圓;類

43、Line為高;類為高;類Cone為圓錐,由為圓錐,由Circle和和Line公有派生而來。在公有派生而來。在Cone類中,類中,Circle和和Line類的類的接口完全不變,可以直接調(diào)用,這就是公有派生的優(yōu)點(diǎn)。在接口完全不變,可以直接調(diào)用,這就是公有派生的優(yōu)點(diǎn)。在Cone的成員函數(shù)中可直接訪問的成員函數(shù)中可直接訪問Circle和和Line中的公有成員和保中的公有成員和保護(hù)成員。護(hù)成員。 【例例8.28.2】由圓和高多重繼承派生出圓錐由圓和高多重繼承派生出圓錐檢證檢證主程序:主程序:圓類圓類Circle定義定義高類高類Line定義定義圓錐類圓錐類Cone定義定義虛基類的引入:虛基類的引入:在圖在

44、圖8.4中,兩個(gè)身份證號(hào)顯然是不合理的。可以把中,兩個(gè)身份證號(hào)顯然是不合理的??梢园裞lass Person這個(gè)共同基類設(shè)置為這個(gè)共同基類設(shè)置為虛基類虛基類,這樣就僅有,這樣就僅有一個(gè)一個(gè)Person基類成員,從不同路徑繼承來的同名數(shù)據(jù)基類成員,從不同路徑繼承來的同名數(shù)據(jù)成員(成員(身份證號(hào)身份證號(hào))在內(nèi)存中就是同一個(gè)數(shù)據(jù)。)在內(nèi)存中就是同一個(gè)數(shù)據(jù)。 8.4 8.4 虛基類(選讀)虛基類(選讀)注意:注意:virtual 關(guān)鍵字只對(duì)緊隨其后的基類名起作用關(guān)鍵字只對(duì)緊隨其后的基類名起作用:class Student: virtual public Person.;class Employee:

45、virtual public Person.;虛基類虛基類(virtual base class)定義:定義:class 派生類名派生類名:virtual 訪問限定符訪問限定符 基類類名基類類名.;class 派生類名派生類名:訪問限定符訪問限定符 virtual 基類類名基類類名.;8.4 8.4 虛基類(選讀)虛基類(選讀)圖圖8.5 采用虛基類后在職研究生類儲(chǔ)存圖采用虛基類后在職研究生類儲(chǔ)存圖StudentGStudentEGStudentPersonStudent新成員新成員GStudent新成員新成員PersonEmployee新成員新成員Person成員成員EGStudent新成員

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

47、1(1(成員對(duì)象參數(shù)名表成員對(duì)象參數(shù)名表1),1), ,成員對(duì)象名成員對(duì)象名m(m(成成員對(duì)象參數(shù)名表員對(duì)象參數(shù)名表m)m),底層虛基類名底層虛基類名1(1(參數(shù)名表參數(shù)名表1)1), , , 底層虛基類名底層虛基類名r(r(參數(shù)名表參數(shù)名表r)r) /派生類新增成員的初始化派生類新增成員的初始化; ; /所列出的成員對(duì)象名全部為新增成員對(duì)象的名字所列出的成員對(duì)象名全部為新增成員對(duì)象的名字在多層虛擬繼承構(gòu)造函數(shù)中,基類名不僅要列出在多層虛擬繼承構(gòu)造函數(shù)中,基類名不僅要列出直接基類,而且要列出底層虛基類,否則編譯器直接基類,而且要列出底層虛基類,否則編譯器認(rèn)為出錯(cuò)。認(rèn)為出錯(cuò)。虛擬繼承的構(gòu)造函數(shù):

48、虛擬繼承的構(gòu)造函數(shù):8.4 8.4 虛基類(選讀)虛基類(選讀)在派生類對(duì)象的在派生類對(duì)象的創(chuàng)建創(chuàng)建中:中:首先是虛基類的構(gòu)造函數(shù)并按它們聲明的順序構(gòu)造。首先是虛基類的構(gòu)造函數(shù)并按它們聲明的順序構(gòu)造。第二批是非虛基類的構(gòu)造函數(shù)按它們聲明的順序調(diào)用。第二批是非虛基類的構(gòu)造函數(shù)按它們聲明的順序調(diào)用。第三批是成員對(duì)象的構(gòu)造函數(shù)。第三批是成員對(duì)象的構(gòu)造函數(shù)。最后是派生類自己的構(gòu)造函數(shù)被調(diào)用。最后是派生類自己的構(gòu)造函數(shù)被調(diào)用。構(gòu)造函數(shù)執(zhí)行次序:構(gòu)造函數(shù)執(zhí)行次序:8.4 8.4 虛基類(選讀)虛基類(選讀)【例例8.3】在采用虛基類的多重繼承中,在采用虛基類的多重繼承中,構(gòu)造與析構(gòu)的次序。構(gòu)造與析構(gòu)的次序

49、。class Dclass:public Bclass1,virtual Bclass3,virtual Bclass2 Object object;public: Dclass():object(),Bclass2(),Bclass3(),Bclass1() cout派生類建立派生類建立!n; Dclass()cout派生類析構(gòu)派生類析構(gòu)!n;void main() Dclass dd; cout主程序運(yùn)行主程序運(yùn)行!n;運(yùn)行結(jié)果:運(yùn)行結(jié)果:Constructor Bclass3/第一個(gè)虛擬基類第一個(gè)虛擬基類,與派生類析構(gòu)函數(shù)排列無關(guān)與派生類析構(gòu)函數(shù)排列無關(guān)Constructor Bclas

50、s2/第二個(gè)虛擬基類第二個(gè)虛擬基類Constructor Bclass1/非虛擬基類非虛擬基類Constructor Object/對(duì)象成員對(duì)象成員派生類建立派生類建立!主程序運(yùn)行主程序運(yùn)行!派生類析構(gòu)派生類析構(gòu)!deconstructor Object/析構(gòu)次序相反析構(gòu)次序相反deconstructor Bclass1deconstructor Bclass2deconstructor Bclass3 /析構(gòu)的次序與構(gòu)造的次序相反。析構(gòu)的次序與構(gòu)造的次序相反。8.4 8.4 虛基類(選讀)虛基類(選讀)對(duì)照?qǐng)D對(duì)照?qǐng)D8.5,盡管,盡管Employee和和Student的構(gòu)造函的構(gòu)造函數(shù)都包含數(shù)

51、都包含Person的構(gòu)造函數(shù),但并未真正調(diào)用。的構(gòu)造函數(shù),但并未真正調(diào)用。唯一的一次調(diào)用是在唯一的一次調(diào)用是在EGStudent構(gòu)造函數(shù)中構(gòu)造函數(shù)中。如。如是非虛基類,則有兩次調(diào)用。是非虛基類,則有兩次調(diào)用。8.4 8.4 虛基類(選讀)虛基類(選讀)【例例8.4】虛基類在多層多重繼承中的應(yīng)用虛基類在多層多重繼承中的應(yīng)用 在職研究生類定義。在職研究生類定義。以虛基類定義公有派生的以虛基類定義公有派生的學(xué)生類學(xué)生類以虛基類定義公有派生的以虛基類定義公有派生的研究生類研究生類以虛基類定義公有派生的以虛基類定義公有派生的教職工類教職工類多重繼承的以虛基類定義多重繼承的以虛基類定義公有派生的公有派生的

52、在職研究生類在職研究生類一、派生類與基類: 在任何需要基類對(duì)象的地方都可以用公有派生類的對(duì)象來在任何需要基類對(duì)象的地方都可以用公有派生類的對(duì)象來代替,這條規(guī)則稱代替,這條規(guī)則稱賦值兼容規(guī)則賦值兼容規(guī)則。它。它包括以下情況:包括以下情況:8.5 8.5 派生類應(yīng)用討論派生類應(yīng)用討論1. 派生類的對(duì)象可以賦值給基類的對(duì)象,這時(shí)是把派生類對(duì)象派生類的對(duì)象可以賦值給基類的對(duì)象,這時(shí)是把派生類對(duì)象中中 從對(duì)應(yīng)基類中繼承來的成員賦值給基類對(duì)象。反過來不從對(duì)應(yīng)基類中繼承來的成員賦值給基類對(duì)象。反過來不行,因?yàn)榕缮惖男鲁蓡T無值可賦。行,因?yàn)榕缮惖男鲁蓡T無值可賦。2. 可以將一個(gè)派生類的對(duì)象的地址賦給其基類

53、的指針變量,但可以將一個(gè)派生類的對(duì)象的地址賦給其基類的指針變量,但只能通過這個(gè)指針訪問派生類中由基類繼承來的成員,不能只能通過這個(gè)指針訪問派生類中由基類繼承來的成員,不能訪問派生類中的新成員。同樣也不能反過來做。訪問派生類中的新成員。同樣也不能反過來做。3. 派生類對(duì)象可以初始化基類的引用。引用是別名,但這個(gè)別派生類對(duì)象可以初始化基類的引用。引用是別名,但這個(gè)別名只能包含派生類對(duì)象中的由基類繼承來的成員。名只能包含派生類對(duì)象中的由基類繼承來的成員?!纠?.5】為例為例8.1定義復(fù)制函數(shù),實(shí)現(xiàn)深復(fù)制。定義復(fù)制函數(shù),實(shí)現(xiàn)深復(fù)制。二、繼承與聚合二、繼承與聚合 繼承使派生類可以利用基類的成員,如果我

54、們把基類的對(duì)象作為繼承使派生類可以利用基類的成員,如果我們把基類的對(duì)象作為一個(gè)新類的對(duì)象成員,也可以取得類似的效果。派生類采用繼承方法,一個(gè)新類的對(duì)象成員,也可以取得類似的效果。派生類采用繼承方法,成員對(duì)象是聚合的概念。成員對(duì)象是聚合的概念。 基類在派生類中只能繼承一個(gè)(間接基類不在討論之中)不能同基類在派生類中只能繼承一個(gè)(間接基類不在討論之中)不能同時(shí)安排兩個(gè),否則成員名即使使用域分辨符也會(huì)發(fā)生沖突:時(shí)安排兩個(gè),否則成員名即使使用域分辨符也會(huì)發(fā)生沖突:class Apublic:int K;.;class B:public A,public A.;兩個(gè)兩個(gè)A無論如何無法分辨出來。無論如何無

55、法分辨出來。如果要用兩個(gè)如果要用兩個(gè)A 只能采用成員對(duì)象只能采用成員對(duì)象 。 更深入地探討后會(huì)發(fā)現(xiàn):成員對(duì)象體現(xiàn)了封裝更深層次的含義。更深入地探討后會(huì)發(fā)現(xiàn):成員對(duì)象體現(xiàn)了封裝更深層次的含義。在派生類和它的基類中是不應(yīng)該有內(nèi)存的動(dòng)態(tài)分配的,動(dòng)態(tài)分配的部在派生類和它的基類中是不應(yīng)該有內(nèi)存的動(dòng)態(tài)分配的,動(dòng)態(tài)分配的部分應(yīng)該封裝在成員對(duì)象中,在該成員對(duì)象的析構(gòu)函數(shù)中釋放內(nèi)存,在分應(yīng)該封裝在成員對(duì)象中,在該成員對(duì)象的析構(gòu)函數(shù)中釋放內(nèi)存,在該成員對(duì)象中提供深復(fù)制該成員對(duì)象中提供深復(fù)制。類。類string就是如此。它的內(nèi)部就是一個(gè)就是如此。它的內(nèi)部就是一個(gè)完完備的小系統(tǒng)備的小系統(tǒng)。這樣程序員就可以放心地使用它

56、,而不需要為它做任何。這樣程序員就可以放心地使用它,而不需要為它做任何事情。事情。 8.5 8.5 派生類應(yīng)用討論派生類應(yīng)用討論8.6 多態(tài)性與虛函數(shù)問題:?jiǎn)栴}:如何用同一個(gè)函數(shù)(同名如何用同一個(gè)函數(shù)(同名函數(shù))求三角形、長(zhǎng)方形、函數(shù))求三角形、長(zhǎng)方形、梯形等不同基本形狀的面梯形等不同基本形狀的面積?積?8.6 8.6 多態(tài)性與虛函數(shù)多態(tài)性與虛函數(shù)多態(tài)性:多態(tài)性: 多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的關(guān)鍵技術(shù)之一。若程序設(shè)計(jì)多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的關(guān)鍵技術(shù)之一。若程序設(shè)計(jì)語言語言不支持多態(tài)性,不能稱為面向?qū)ο蟮恼Z言不支持多態(tài)性,不能稱為面向?qū)ο蟮恼Z言。利用多態(tài)性技。利用多態(tài)性技術(shù),可以調(diào)用同一個(gè)函數(shù)名

57、的函數(shù),實(shí)現(xiàn)完全不同的功能。術(shù),可以調(diào)用同一個(gè)函數(shù)名的函數(shù),實(shí)現(xiàn)完全不同的功能。在在C+中有兩中有兩種多態(tài)種多態(tài)性性 編譯時(shí)的多態(tài)性編譯時(shí)的多態(tài)性 運(yùn)行時(shí)的運(yùn)行時(shí)的多態(tài)性多態(tài)性 運(yùn)行時(shí)的多態(tài)性是指在程序執(zhí)行運(yùn)行時(shí)的多態(tài)性是指在程序執(zhí)行前,無法根據(jù)函數(shù)名和參數(shù)來確前,無法根據(jù)函數(shù)名和參數(shù)來確定該調(diào)用哪一個(gè)函數(shù),必須在程定該調(diào)用哪一個(gè)函數(shù),必須在程序執(zhí)行過程中,根據(jù)執(zhí)行的具體序執(zhí)行過程中,根據(jù)執(zhí)行的具體情況來動(dòng)態(tài)地確定。它是情況來動(dòng)態(tài)地確定。它是通過類通過類繼承關(guān)系和虛函數(shù)來實(shí)現(xiàn)的。繼承關(guān)系和虛函數(shù)來實(shí)現(xiàn)的。目的目的也是建立一種通用的程序也是建立一種通用的程序。通用性。通用性是程序追求的主要目標(biāo)之

58、一。是程序追求的主要目標(biāo)之一。 通過函數(shù)的重載和運(yùn)算通過函數(shù)的重載和運(yùn)算符的重載來實(shí)現(xiàn)的。符的重載來實(shí)現(xiàn)的。8.6 多態(tài)性與虛函數(shù)8.6.1 虛函數(shù)的定義虛函數(shù)的定義 8.6.4 動(dòng)態(tài)綁定動(dòng)態(tài)綁定 (選讀)(選讀) 8.6.2 純虛函數(shù)純虛函數(shù) 8.6.3 繼承與多態(tài)的應(yīng)用繼承與多態(tài)的應(yīng)用單鏈表派生類(選讀)單鏈表派生類(選讀) 8.6.1 8.6.1 虛函數(shù)的定義虛函數(shù)的定義虛函數(shù)的概念:虛函數(shù)的概念:虛函數(shù)是一個(gè)類的成員函數(shù),定義格式如下:虛函數(shù)是一個(gè)類的成員函數(shù),定義格式如下:virtual 返回類型返回類型 函數(shù)名(參數(shù)表);函數(shù)名(參數(shù)表);關(guān)鍵字關(guān)鍵字virtual指明該成員函數(shù)為

59、虛函數(shù)。指明該成員函數(shù)為虛函數(shù)。virtual僅僅用于類定義中,如虛函數(shù)在類外定義,不可再加用于類定義中,如虛函數(shù)在類外定義,不可再加virtual。當(dāng)一個(gè)類的某個(gè)成員函數(shù)被定義為虛函數(shù),則由該當(dāng)一個(gè)類的某個(gè)成員函數(shù)被定義為虛函數(shù),則由該類派生出來的所有派生類中,該函數(shù)始終保持虛函類派生出來的所有派生類中,該函數(shù)始終保持虛函數(shù)的特征。數(shù)的特征。8.6.1 8.6.1 虛函數(shù)的定義虛函數(shù)的定義當(dāng)在派生類中重新定義虛函數(shù)(當(dāng)在派生類中重新定義虛函數(shù)(overriding a virtual function,亦譯作超載或覆蓋)時(shí),不必加亦譯作超載或覆蓋)時(shí),不必加關(guān)鍵字關(guān)鍵字virtual。但重新

60、定義時(shí)不僅要同名,而且它。但重新定義時(shí)不僅要同名,而且它的參數(shù)表和返回類型全部與基類中的虛函數(shù)一樣,的參數(shù)表和返回類型全部與基類中的虛函數(shù)一樣,否則出錯(cuò)。否則出錯(cuò)。虛函數(shù)與在虛函數(shù)與在8.1.1節(jié)中介紹的派生類的第二步節(jié)中介紹的派生類的第二步改造類成員,同名覆蓋(改造類成員,同名覆蓋(override)有關(guān):如未)有關(guān):如未加關(guān)鍵字加關(guān)鍵字virtual,則是普通的派生類中的新成員,則是普通的派生類中的新成員函數(shù)覆蓋基類同名成員函數(shù)(當(dāng)然參數(shù)表必須一函數(shù)覆蓋基類同名成員函數(shù)(當(dāng)然參數(shù)表必須一樣,否則是重載),可稱為樣,否則是重載),可稱為同名覆蓋函數(shù)同名覆蓋函數(shù),它,它不不能實(shí)現(xiàn)運(yùn)行時(shí)的多態(tài)性

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論