版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、第4篇面向?qū)ο蟮某绦蛟O(shè)計第11章第12章第13章第14章繼承與派生多態(tài)性與虛函數(shù)輸入輸出流C+工具11.1 繼承與派生的概念11.2 派生類的11.3 派生類的11.4 派生類成員的方式屬性11.5 派生類的構(gòu)造函數(shù)和析11.6 多重繼承11.7 基類與派生類的轉(zhuǎn)換11.8 繼承與組合數(shù)11.9 繼承在開發(fā)中的重要意義第11章 繼承與派生面向?qū)ο蟪绦蛟O(shè)計有4個主要特點: 抽象、封裝、繼承和多態(tài)性。要較好地進(jìn)行面向?qū)ο蟪绦蛟O(shè)計,還必須了解面向?qū)ο蟪绦蛟O(shè)計另外兩個重要特征繼承性和多態(tài)有關(guān)繼承的知識,在第12章性。在本章中主要中將多態(tài)性。面向?qū)ο蠹夹g(shù)強調(diào)的可重用性(softwarereusabili
2、ty) 。CC+語+ 言提供了類的繼承機制,解決了重用。11.1 繼承與派生的概念在C+中可重用性是通過繼承(inheritance)這一機制來實現(xiàn)的。繼承是C+的一個重要組成部分。一個類中包含了若干數(shù)據(jù)成員和成員函數(shù)。在不同的類中,數(shù)據(jù)成員和成員函數(shù)是不相同的。但有時兩個類的內(nèi)容基本相同或有一部分相同。的類Student作為基礎(chǔ),再加上新的利用原來內(nèi)容即可,以減少重復(fù)的工作量。 C+提供的繼承機制就是為了解決這個。在第8章已舉了馬的例子來說明繼承的概念。見圖11.1示意。在C+中,所謂“繼承”就是在一個已的類的基的類(例如“馬”)稱為礎(chǔ)上建立一個新的類。已“基類(base class)”或“
3、父類(father class)”。新建立的類(例如“公馬”)稱為“派生類(derived class)”或“子類(son class)”。見圖11.2示意。圖11.1圖11.2一個新類從已有的類那里獲得其已有特性,這種現(xiàn)象稱為類的繼承。通過繼承,一個新建子類從已有的父類那里獲得父類的特性。從另一角度說,從已有的類(父類)產(chǎn)生一個新的子類,稱為類的派生。類的繼承是用已有的類來建立類的編程技術(shù)。派生類繼承了基類的所有數(shù)據(jù)成員和成員函數(shù),并可以對成員作必要的增加或調(diào)整。一個基類可以派生出多個派生類,每一個派生類又可以作為基類再派生出新的派生類,因此基類和派生類是相對而言的。的是最簡單的情況: 一個
4、派生類只從一個以上基類派生,這稱為單繼承(single inheritance),這種繼承所形成的層次是一個樹形結(jié)構(gòu),可以用圖11.3表示。圖11.3請注意圖中箭頭的方向,中約定,箭頭表示繼承的方向,從派生類指向基類。一個派生類不僅可以從一個基類派生,也可以從多個基類派生。一個派生類有兩個或多個基類的稱為多重繼承(multiple inheritance),這種繼承形成的結(jié)構(gòu)如圖11.4所示。所圖11.4,可以表述為: 派生類是關(guān)于基類和派生類的基類的具體化,而基類則是派生類的抽象。圖11.511.2 派生類的方式假設(shè)已經(jīng)了一個基類Student,在此基礎(chǔ)上通過單繼承建立一個派生類Studen
5、t1:class Student1: public Student/public:void display_1( )cout<<age: <<age<<eend;l基類是Student/新增加的成員函數(shù)cout<<address: <<aadd<r<<eend;lprivate:int age; string addr;/新增加的數(shù)據(jù)成員/新增加的數(shù)據(jù)成員基類名前面有public的稱為“公用繼承(publicinheritance)”。派生類的一般形式為class 派生類名: 繼承方式 基類名派生類新增加的成員 ;:
6、 public(公用的),private(私有的)和繼承方式protected(受保護(hù)的),此項是可選的,如果不寫此項,則默認(rèn)為private(私有的)。11.3 派生類的派生類中的成員從基類繼承過來的成員和增加的成員兩大部分。在基類中數(shù)據(jù)成員和成員函數(shù)(或稱數(shù)據(jù)與)兩部分,派生類分為兩大部分: 一部分是從基類繼承來的成員,另一部分是在派生類時增加的部分。每一部分均分別數(shù)據(jù)成員和成員函數(shù)。圖11.6實際上,并不是把基類的成員和派生類增加的成員簡單地加在一起就成為派生類。構(gòu)造一個派生類以下3部分工作:(1) 從基類接收成員。派生類把基類全部的成員(不數(shù))接收過來,也就是說是構(gòu)造函數(shù)和析沒有選擇的
7、,不能選擇接收其中一部分成員,而舍棄另一部分成員。要求我們根據(jù)派生類的需要慎重選擇基類,使冗余量最小。事實上,有些類是專門作為基類而設(shè)計 的,在設(shè)計時充分考慮到派生類的要求。(2) 調(diào)整從基類接收的成員。接收基類成員是程序不能選擇的,但是程序某些調(diào)整??梢詫@些成員作(3) 在派生類時增加的成員。這部分內(nèi)容是很重要的,它體現(xiàn)了派生類對基類功能的擴(kuò)展。要根據(jù)需要仔細(xì)考慮應(yīng)當(dāng)增加哪些成員,精心設(shè)計。此外,在派生類時,一般還應(yīng)當(dāng)定義派生類的構(gòu)造函數(shù)和析數(shù),因為構(gòu)造函數(shù)和析數(shù)是不能從基類繼承的。派生類是基類定義的延續(xù)??梢韵纫粋€基類,在此基類中只提供某些最基本的功能,而另外有些功能并未實現(xiàn),然后在派生
8、類時加入某些具體的功能,形成適用于某一特定應(yīng)用的派生類。通過對基類的延續(xù),將一個抽象的基類轉(zhuǎn)化成具體的派生類。因此,派生類是抽象基類的具體實現(xiàn)。11.4 派生類成員的屬性既然派生類中包含基類成員和派生類增加的成屬性的問員,就產(chǎn)生了這兩部分成員的和題。在建立派生類的時候,并不是簡單地把基類的私有成員直接作為派生類的私有成員,把基類的公用成員直接作為派生類的公用成員。實際上,對基類成員和派生類理的。增加的成員是按不同的原則處具體說,在討論況:(1) 基類的成員函數(shù)屬性時,要考慮以下幾種情基類成員。派生類(2) 派生類的成員函數(shù)(3) 基類的成員函數(shù)(4) 派生類的成員函數(shù)增加的成員。派生類的成員。
9、基類的成員。(5) 在派生類外(6) 在派生類外派生類的成員?;惖某蓡T。對于第(1)和第(2)種情況,比較簡單,按第8章過的規(guī)則處理,即: 基類的成員函數(shù)可以基類成員,派生類的成員函數(shù)可以派生類成員。私有數(shù)據(jù)成員只能被同一類中的成員函數(shù),公用成員可以被外界。第(3)種情比較明確,基類的成員函數(shù)只能派生類的成員。第(5)種情基類的成員,而不能比較明確,在派生類外可以派生類的公用成員,而不能派生類的私有成員。對于第(4)和第(6)種情況,就稍微復(fù)雜一些,也容易。這些牽涉到如何確定基類的成員在派生類中的屬性的,不僅要考慮對基類成員所的屬性,還要考慮派生類所的對基類的繼承方式,根據(jù)這兩個因素共同決定
10、基類成員在派生類中的屬性。前面已提到: 在派生類中,對基類的繼承方式可以有public(公用的),private(私有的)和protected(保護(hù)的)3種。不同的繼承方式?jīng)Q定了基類成員在派生類中的簡單地說:屬性。(1) 公用繼承(public inheritance)基類的公用成員和保護(hù)成員在派生類中保持原有訪問屬性,其私有成員仍為基類私有。(2) 私有繼承(private inheritance)基類的公用成員和保護(hù)成員在派生類中成了私有成員。其私有成員仍為基類私有。(3) 受保護(hù)的繼承(protected inheritance)基類的公用成員和保護(hù)成員在派生類中成了保護(hù)成員,其私有成員
11、仍為基類私有。保護(hù)成員的意思是: 不能被外界,但可以被派生類的成員,具體的用法將在稍后。11.4.1 公用繼承在定義一個派生類時將基類的繼承方式指定為public的,稱為公用繼承,用公用繼承方式建立的派生類稱為公用派生類(public derived class),其基類稱為公用基類(public base class)。采用公用繼承,基類的公用成員和保護(hù)成員在派生類中仍然保持其公用成員和保護(hù)成員的屬性,而基類的私有成員在派生類中并沒有成為派生類的私有成員,它仍然是基類的私有成員,只有基類的成員函數(shù)可以它,而不能被派生類的成員函數(shù),因此就成為派生類中的不可的成員。公用基類的成員在派生類中的11
12、.1。屬性見書中表例11.1公有基類的成員。部分:下面寫出類的Class Student/public:void get_value( )基類/基類公用成員cin>>num>>name>>sex; void display( )cout<< num: <<<num<<eend;l cout<< name: <<name<<endl;cout<< sex: <<sex<<endl;private : int num;string name; cha
13、r sex;/基類私有成員class Student1: public Student/以ppubli方c式派生類Student1public:void display_1( )cout<< num: <<num<<endl; cout<< name: <<name<<endl; cout<< sex: <<sex<<endl;cout<< age: <<age<<endl;/企圖/企圖/企圖基類的私有成員,錯誤基類的私有成員,錯誤基類的私有成員,錯誤
14、/派生類的私有成員,正確派生類的私有成員,正確cout<< address: <<addr<<endl; private:int age; string addr;/由于基類的私有成員對派生類來說是不可因此在派生類中的display_1函數(shù)中直接的,基類的私有數(shù)據(jù)成員num,name和sex是不的。只能通過基類的公用成員函數(shù)來員。基類的私有數(shù)據(jù)成可以將派生類Student1的class Student1: public Student/以ppubli方cpublic:void display_1( )改為派生類Student1式cout<< ag
15、e: <<age<<endl; cout<< address: <<<aadd<r<<eend;lprivate: int age;string addr;/派生類的私有成員,正確派生類的私有成員,正確/然后在main函數(shù)中分別調(diào)用基類的display函數(shù)和派生類中的display_1函數(shù),先后輸出5個數(shù)據(jù)??梢赃@樣寫main函數(shù)(假設(shè)對象stud中已有數(shù)據(jù)):int main( )Student1 stud;/定義派生類Student1的對象studstud.display( ); stud.display_1();的值
16、return 0;/調(diào)用基類的公用成員函數(shù),輸出基類中3個數(shù)據(jù)成員的值/調(diào)用派生類的公用成員函數(shù),輸出派生類中兩個數(shù)據(jù)成員請根據(jù)上面的分析,寫出完整的程序,括輸入數(shù)據(jù)的函數(shù)。應(yīng)包實際上,程序還可以改進(jìn),在派生類的display_1函數(shù)中調(diào)用基類的display函數(shù),在主函數(shù)中只要寫一行:stud.display_1();即可輸出5個數(shù)據(jù)。11.4.2 私有繼承在一個派生類時將基類的繼承方式指定為private的,稱為私有繼承,用私有繼承方式建立的派生類稱為私有派生類(private derived class) ,其基類稱為私有基類(private base class)。私有基類的公用成員和
17、保護(hù)成員在派生類中的屬性相當(dāng)于派生類中的私有成員,即派生類的成員函數(shù)能它們,而在派生類外不能它們。私的成有基類的私有成員在派生類中成為不可員,只有基類的成員函數(shù)可以它們。一個基類成員在基類中的屬性和在派生類中的屬性可能是不同的。私有基類的成員在私有派生類中的屬性見書中表11.2。圖11.7圖11.7表示了各成員在派生類中的屬性。對表11.2的規(guī)定不必死記,只需理解: 既然為私有繼承,就表示將原來能被外界的成員隱藏起來,不讓外界,因此私有基類的公用成員和保護(hù)成員理所當(dāng)然地成為派生類中的私有成員。私有基類的私有成員按規(guī)定只能被基類的成員函數(shù)引用,在基類外當(dāng)然不能類中是隱蔽的,不可他們,因此它們在派
18、生的。對于不需要再往下繼承的類的功能可以用私有繼承方式把它隱蔽起來,這樣,下一層的派生類無法訪問它的任何成員??梢灾? 一個成員在不同的派生層次中的性可能是不同的。它與繼承方式有關(guān)。屬例11.2 將例11.1中的公用繼承方式改為用私有繼承方式(基類Student不改)??梢詫懗鏊接信缮惾缦?class Student1: private Student/用私有繼承方式public:派生類Student1/輸出兩個數(shù)據(jù)成員的值void display_1( )cout<<age: <<age<<eend;l/派生類的私有成員,正確派生類的私有成員,正確co
19、ut<<address: <<aadd<r<<eend;l private:int age; string addr;請分析下面的主函數(shù):int main( )/Student1 stud1;/定義一個Student1類的對象stud1stud1.display(); 數(shù)stud1.display_1( ); stud1.age=18;return 0;/錯誤,私有基類的公用成員函數(shù)在派生類中是私有函/正確。DDisplay_函1 數(shù)是Student1類的公用函數(shù)/錯誤。外界不能派生類的私有成員可以看到:(1) 不能通過派生類對象(如stud1)從私有
20、基類繼承過來的任何成員(如stud1.display()或stud1.num)。(2) 派生類的成員函數(shù)不能私有基類的私有成員,但可以私有基類的公用成員(如stud1.display_1函數(shù)可以調(diào)用基類的公用成員函數(shù)display,但不能基類的私有成員num)。有沒有辦法調(diào)用私有基類的公用成員函數(shù),從而引用私有基類的私有成員呢?有。應(yīng)當(dāng)注意到: 雖然在派生類外不能通過派生類對象調(diào)用私有基類的公用成員函數(shù),但可以通過派生類的成員函數(shù)調(diào)用私有基類的公用成員函數(shù)(此時它是派生類中的私有成員函數(shù),可以被派生類的任何成員函數(shù)調(diào)用)??蓪⑸厦娴乃接信缮惖某蓡T函數(shù)定義改寫為void display_1(
21、)/輸出5個數(shù)據(jù)成員的值display():/調(diào)用基類的公用成員函數(shù),輸出3個數(shù)據(jù)成員的值cout<<age: <<age<<endl;/輸出派生類的私有數(shù)據(jù)成員cout<<address: <<addr<<endl; /輸出派生類的私有數(shù)據(jù)成員main函數(shù)可改寫為int main( )Student1 stud1;stud1.display_1( );/display_1函數(shù)是派生類Student1類的公用函數(shù)return 0;這樣就能正確地到,本例采用的私有基類的私有成員??梢钥词? 在main函數(shù)中調(diào)用派生類中的公用
22、成員函數(shù)stud1.display_1; 通過該公用成員函數(shù)調(diào)用基類的公用成員函數(shù)display(它在派生類中是私有函數(shù),可以被派生類中的任何成員函數(shù)調(diào)用); 通過基類的公用成員函數(shù)display數(shù)據(jù)成員。請根據(jù)上面的要求,補充和完善上面的程序,使之基類中的成為完整、正確的程序。函數(shù)。應(yīng)輸入數(shù)據(jù)的由于私有派生類限制太多,使用不方便,一般不常使用。11.4.3 保護(hù)成員和保護(hù)繼承的成員稱為“受保護(hù)的成員”,或簡由protected稱“保護(hù)成員”。從類的用戶角度來看,保護(hù)成員等價于私有成員。但有一點與私有成員不同,保護(hù)成員可以被派生類的成員函數(shù)。見圖11.8示意。圖11.8如果基類了私有成員,那么
23、任何派生類都是不能它們的,若希望在派生類中能它們,應(yīng)當(dāng)把它們?yōu)楸Wo(hù)成員。如果在一個類中了保護(hù)成員,就意味著該類可能要用作基類,在它的派生類中會這些成員。在定義一個派生類時將基類的繼承方式指定為protected的,稱為保護(hù)繼承,用保護(hù)繼承方式建立的派生類稱為保護(hù)派生類(protected derived class),其基類稱為受保護(hù)的基類(protected base class),簡稱保護(hù)基類。保護(hù)繼承的特點是: 保護(hù)基類的公用成員和保護(hù)成員在派生類中都成了保護(hù)成員,其私有成員仍為基類私有。也就是把基類原有的公用成員也保護(hù)起來,不讓類外任意。將表11.1和表11.2綜合起來,并增加保護(hù)繼承
24、的內(nèi)容,見書中表11.3。保護(hù)基類的所有成員在派生類中都被保護(hù)起來,類外不能,其公用成員和保護(hù)成員可以被其派生類的成員函數(shù)。比較一下私有繼承和保護(hù)繼承(也就是比較在私有派生類中和在保護(hù)派生類中的屬性),可以發(fā)現(xiàn),在直接派生類中,以上兩種繼承方式的作用實際上是相同的: 在類外不能生類中可以通過成員函數(shù)任何成員,而在派基類中的公用成員和保護(hù)成員。但是如果繼續(xù)派生,在新的派生類中,兩種繼承方式的作用就不同了。例如,如果以公用繼承方式派生出一個新派生類,原來私有基類中的成員在新派生類中都成為不可訪問的成員,無論在派生類內(nèi)或外都不能,而原來保護(hù)基類中的公用成員和保護(hù)成員在新派生類中為保護(hù)成員,可以被新派
25、生類的成員函數(shù)。從表11.3可知: 基類的私有成員被派生類繼承后變?yōu)椴豢傻某蓡T,派生類中的一切成員均無法訪問它們。如果需要在派生類中員,應(yīng)當(dāng)將基類的這些成員基類的某些成為protected,而不要如果為private。利用保護(hù)成員,可以在類的層次結(jié)構(gòu)中找到數(shù)據(jù)共享與成員隱蔽之間的結(jié)合點。既可實現(xiàn)某些成員的隱蔽,又可方便地繼承,能實現(xiàn)代碼重用與擴(kuò)充。,可以知道:通過以上的(1) 在派生類中,成員有4種不同的屬性: 公用的,派生類內(nèi)和派生類外都可以。 受保護(hù)的,派生類內(nèi)可以問,其下一層的派生類可以 私有的,派生類內(nèi)可以,派生類外不能訪。,派生類外不能。 不可可以的,派生類內(nèi)和派生類外都不能中表11
26、.4表示。需要說明的是: 這里所列出的成員的屬性是指在派生類中所獲得的屬性。 所謂在派生類外部,是指在建立派生類對象的模塊中,在派生類范圍之外。 如果本派生類繼續(xù)派生,則在不同的繼承方式下,成員所獲得的屬性是不同的,在本表中只列出在下一層公用派生類中的情況,如果是私有繼承或保護(hù)繼承,讀者可以從表11.3中找到(2) 類的成員在不同作用域中有不同的對這一點要十分清楚。屬性,下面通過一個例子說明怎樣保護(hù)成員。例11.3 在派生類中#include <iostream> #include <string> using namespace std;保護(hù)成員。class Stud
27、ent/public:void display( ); protected :int num; string name; char sex;基類/基類公用成員/基類保護(hù)成員void Student:display( )/定義基類成員函數(shù)cout<<num: <<<num<<eend;l cout<<name: <<name<<endl; cout<<sex: <<sex<<eend;l/用protected方式派生類Student1class Student1: protected
28、 Studentpublic:void display1( );/派生類公用成員函數(shù)private: int age;string addr;/派生類私有數(shù)據(jù)成員/派生類私有數(shù)據(jù)成員void Student1:display1( )cout<<num: <<num<<endl; cout<<name: <<name<<endl; cout<<sex: <<sex<<endl; cout<<age: <<age<<endl;/定義派生類公用成員函數(shù)/基類
29、的保護(hù)成員,合法基類的保護(hù)成員,合法/基類的保護(hù)成員,合法派生類的私有成員,合法 派生類的私有成員,合法/cout<<address: <<addr<<endl;/int main( )Student1 stud1; stud1.display1( ); stud1.num=10023; return 0;/stud1是派生類Student1類的對象/合法,display1是派生類中的公用成員函數(shù)/錯誤,外界不能保護(hù)成員在派生類的成員函數(shù)中基類的保護(hù)成員是合法的。保護(hù)成員和私有成員不同之處,在于把保護(hù)成員的注意: 在范圍擴(kuò)展到派生類中。通過派生類Studen
30、t1的對象stud1的公用成員函數(shù)display1去基類的保護(hù)成員和sex,不要誤認(rèn)為可以通過派生類對象基類的保護(hù)成員。名去請補充、修改上面的程序,使之能正常運行。程序中應(yīng)輸入數(shù)據(jù)的函數(shù)。私有繼承和保護(hù)繼承方式在使用時需要十分很容易搞錯,一般不常用。,11.4.4 多級派生時的屬性圖11.9如果有圖11.9所示的派生: 類A為基類,類B是類A的派生類,類C是類B的派生類,則類C也是類A的派生類。類B稱為類A的直接派生類,類C稱為類A的間接派生類。類A是類B的直接基類,是類C 的間接基類。在多級派生的情況下,各成員的屬性仍按以上原則確定。例11.4 多級派生的屬性。了以下的類:/基類如果clas
31、s Apublic: int i; protected: void f2( ); int j; private: int k;class B: public Apublic: void f3( ); protected: void f4( ); private: int m;/public方式class C: protected Bpublic: void f5( ); private: int n;/protected方式類A是類B的公用基類,類B是類C的保護(hù)基類。各屬性如下:成員在不同類中的if2jkf3f4mf5n基類A公用保護(hù)保護(hù)私有公 用派 生類B公用保護(hù)保護(hù)不可公用保護(hù)私有保 護(hù)派
32、 生類C保護(hù)保護(hù)保護(hù)不可保護(hù)保護(hù)不可公用私有無論哪一種繼承方式,在派生類中是不能基類的私有成員的,私有成員只能被本類的成員函數(shù)所,畢竟派生類與基類不是同一個類。如果在多級派生時都采用公用繼承方式,那么直到最后一級派生類都能基類的公用成員和保護(hù)成員。如果采用私有繼承方式,經(jīng)過若干次派生之后,基類的所有的成員已經(jīng)變成不可繼承方式,在派生類外是無法的了。如果采用保護(hù)派生類中的任何成員的。而且經(jīng)過多次派生后,人們很難清楚地記住哪些成員可以,哪些成員不能,很容易出錯。因此,在實際中,常用的是公用繼承。11.5 派生類的構(gòu)造函數(shù)和析數(shù)用戶在類時可以不定義構(gòu)造函數(shù),系統(tǒng)會自動設(shè)置一個默認(rèn)的構(gòu)造函數(shù),在定義類
33、對象時會自動調(diào)用這個默認(rèn)的構(gòu)造函數(shù)。這個構(gòu)造函數(shù)實際上是一個空函數(shù),不執(zhí)行任何操作。如果需要對類中的數(shù)據(jù)成員初始化,應(yīng)定義構(gòu)造函數(shù)。構(gòu)造函數(shù)的主要作用是對數(shù)據(jù)成員初始化。在設(shè)計派生類的構(gòu)造函數(shù)時,不僅要考慮派生類所增加的數(shù)據(jù)成員的初始化,還應(yīng)當(dāng)考慮基類的數(shù)據(jù)成員初始化。也就是說,希望在執(zhí)行派生類的構(gòu)造函數(shù)時,使派生類的數(shù)據(jù)成員和基類的數(shù)據(jù)成員同時都的思路是: 在執(zhí)行派生類被初始化。解決這個的構(gòu)造函數(shù)時,調(diào)用基類的構(gòu)造函數(shù)。11.5.1 簡單的派生類的構(gòu)造函數(shù)任何派生類都包含基類的成員,簡單的派生類只有一個基類,而且只有一級派生(只有直接派生類, 沒有間接派生類),在派生類的數(shù)據(jù)成員中不包含基類
34、的對象(即子對象)。例11.5 簡單的派生類的構(gòu)造函數(shù)。#include <iostream> #include<string> using namespace std;class Student/public:基類StudentStudent(int n,string nnam,char s)num=n; name=nam; sex=s; /基類構(gòu)造函數(shù)Student( ) /基類析數(shù)protected: int num; string name; char sex ;/保護(hù)部分;class Student1: public Student/派生類Student1pu
35、blic:/派生類的公用部分Student1(int n,string nnam,char s,iinta,s,striing ad):Student(n,nnam,s)/派生類構(gòu)造函數(shù)age=a;addr=ad;void show( )/在函數(shù)體中只對派生類新增的數(shù)據(jù)成員初始化cout<<num: <<<num<<eend;l cout<<name: <<name<<endl; cout<<sex: <<sex<<eend;l cout<<age: <<a
36、ge<<endl;cout<<address: <<<aadd<r<<eend<l <<eend;lStudent1( ) private:/派生類析數(shù)/派生類的私有部分int age; string addr;int main( )Student1 stud1(10010,WaWang,-lfi,19,115Road,Shanghai);Student1 stud2(10011,Zhang-fun,m,21,213 Shanghai Road,);stud1.show( );stud2.show( ); retur
37、n 0;/輸出第一個學(xué)生的數(shù)據(jù)/輸出第二個學(xué)生的數(shù)據(jù)運行結(jié)果為num:10010name:Wang-li sex:faddress: 115Road,Shanghainum:10011 name:Zhang-fun sex:maddress: 213 Shanghai Road,請注意派生類構(gòu)造函數(shù)首行的寫法:Student1(int n,string nam,char s,int a,string ad):Student(n,nam,s)其一般形式為派生類構(gòu)造函數(shù)名(總參數(shù)表列): 基類構(gòu)造函數(shù)名(參數(shù)表列)派生類中新增數(shù)據(jù)成員初始化語句在main函數(shù)中,建立對象stud1時指定了5個實參。
38、它們按順序傳遞給派生類構(gòu)造函數(shù)Student1的形參。然后,派生類構(gòu)造函數(shù)將前面3個傳遞給基類構(gòu)造函數(shù)的形參。見圖11.10。圖11.10通過Student (n, nam, s)把3個值再傳給基類構(gòu)造函數(shù)的形參,見圖11.11。Student(n,n,nam,s)Student(intstring nam,char s)/這是基類構(gòu)造函數(shù)的首部圖11.1111.11在上例中也可以將派生類構(gòu)造函數(shù)在類外面定義,而在類體中只寫該函數(shù)的:Student1(int n,string nam,char s,int a,string ad);在類的外面定義派生類構(gòu)造函數(shù):Student1Student1
39、(int n,string nam,char s,int a,string ad):Student(n,nam,s)age=a; addr=ad;請注意: 在類中對派生類構(gòu)造函數(shù)作時,不基類構(gòu)造函數(shù)名及其參數(shù)表列(即Student(n,nam,s))。只在定義函數(shù)時才將它列出。在以上的例子中,調(diào)用基類構(gòu)造函數(shù)時的實參是從派生類構(gòu)造函數(shù)的總參數(shù)表中得到的,也可以不從派生類構(gòu)造函數(shù)的總參數(shù)表中傳遞過來,而直接使用常量或全局變量。例如,派生類構(gòu)造函數(shù)首行可以寫成以下形式:Student1(string nam,char s,int a,string ad):Student(10010,nam,s)即
40、基類構(gòu)造函數(shù)3個實參中,有一個是常量10010, 另外兩個從派生類構(gòu)造函數(shù)的總參數(shù)表傳遞過來。請回顧一下在第9章子:過的構(gòu)造函數(shù)初始化表的例Box:Box(int h,int w,int len):height(h),width(w),length(len) 它也有一個冒號,在冒號后面的是對數(shù)據(jù)成員的初始化表。實際上,本章的在派生類構(gòu)造函數(shù)中對基類成員初始化,就是在第9章的構(gòu)造函數(shù)初始化表。也就是說,不僅可以利用初始化表對構(gòu)造函數(shù)的數(shù)據(jù)成員初始化,而且可以利用初始化表調(diào)用派生類的基類構(gòu)造函數(shù),實現(xiàn)對基類數(shù)據(jù)成員的初始化。也可以在同一個構(gòu)造函數(shù)的定義中同時實現(xiàn)這兩種功能。例如,例11.5中派生類
41、的基類構(gòu)造函數(shù)的定義采用了下面的形式:Student1(int n, string nam,char s,int a, string ad):Student(n,nam,s)age=a;/在函數(shù)體中對派生類數(shù)據(jù)成員初始化addr=ad;可以將對age和addr的初始化也用初始化表處理,將構(gòu)造函數(shù)改寫為以下形式:Student1(int n, string nam,char s,int a, string ad):Student(n,nam,s),age(a),addr(ad)這樣函數(shù)體為空,更顯得簡單和方便。在建立一個對象時,執(zhí)行構(gòu)造函數(shù)的順序是: 派生類構(gòu)造函數(shù)先調(diào)用基類構(gòu)造函數(shù);再執(zhí)行派生
42、類構(gòu)造函數(shù)本身(即派生類構(gòu)造函數(shù)的函數(shù)體)。對上例來說,先初始化num,name,sex,然后再初始化age和addr。在派生類對象時,先執(zhí)行派生類析數(shù)Student1( ),再執(zhí)行其基類析數(shù)Student( )。11.5.2 有子對象的派生類的構(gòu)造函數(shù)類的數(shù)據(jù)成員中還可以包含類對象,如可以在一個類時包含這樣的數(shù)據(jù)成員:Student s1;/ Student是已的類名,s1是Student類的對象這時,s1就是類對象中的內(nèi)嵌對象,稱為子對象(subobject),即對象中的對象。通過例子來說明。例11.6 包含子對象的派生類的構(gòu)造函數(shù)。為了簡化程序以易于閱讀,這里設(shè)基類Student的數(shù)據(jù)成
43、員只有兩個,即num和name。#include <iostream> #include <string> using namespace std;class Student/public:基類/公用部分/基類構(gòu)造函數(shù),與例11.5相同Student(int n, string nam )num=n; name=nam;void display( )/成員函數(shù),輸出基類數(shù)據(jù)成員cout<<nnum:<<<num<<eend<l <<nname:<<<name<<eend;lprot
44、ected: int num;string name;/保護(hù)部分class Student1: public Student/公用派生類Student1public:Student1(int n, string nam,int n1, string nam1,int a, string ad):Student(n,nam),monitor(n1,nam1)age=a; addr=ad;void show( )cout<<This student is:<<endl;/派生類構(gòu)造函數(shù)display();cout<<age: <<age<<
45、;endl;/輸出num和name/輸出agecout<<address: <<addr<<endl<<endl;/輸出addrvoid show_monitor( )/成員函數(shù),輸出子對象cout<<endl<<Class monitor is:<<endl;/調(diào)用基類成員函數(shù)monitor.display( );private:Student monitor; int age;string addr;/派生類的私有數(shù)據(jù)/定義子對象(班長)int main( )Student1 stud1(10010,Wan
46、g-li,10001,Li-sun,19,115 Road,Shanghai);stud1.show( ); stud1.show_monitor();return 0;/輸出學(xué)生的數(shù)據(jù)/輸出子對象的數(shù)據(jù)運行時的輸出如下:This student is: num: 10010 name: Wang-liage: 19address:115Road,ShanghaiClass monitor is:num:10001 name:Li-sun3個部分:派生類構(gòu)造函數(shù)的任務(wù)應(yīng)該(1) 對基類數(shù)據(jù)成員初始化;(2) 對子對象數(shù)據(jù)成員初始化;(3) 對派生類數(shù)據(jù)成員初始化。派生類構(gòu)造函數(shù)首部如下:Stu
47、dent1(int n, string nam,int n1, string nam1,int a, string ad):SStudent( n,am),monitor(n1,nam1)在上面的構(gòu)造函數(shù)中有6個形參,前兩個作為基類構(gòu)造函數(shù)的參數(shù),第3、第4個作為子對象構(gòu)造函數(shù)的參數(shù),第5、第6個是用作派生類數(shù)據(jù)成員初始化的。見圖11.12。圖11.12歸納起來,定義派生類構(gòu)造函數(shù)的一般形式為派生類構(gòu)造函數(shù)名(總參數(shù)表列): 基類構(gòu)造函數(shù)名(參數(shù)表列),子對象名(參數(shù)表列)派生類中新增數(shù)成員據(jù)成員初始化語句執(zhí)行派生類構(gòu)造函數(shù)的順序是: 調(diào)用基類構(gòu)造函數(shù),對基類數(shù)據(jù)成員初始化; 調(diào)用子對象構(gòu)造函
48、數(shù),對子對象數(shù)據(jù)成員初始化; 再執(zhí)行派生類構(gòu)造函數(shù)本身,對派生類數(shù)據(jù)成員初始化。派生類構(gòu)造函數(shù)的總參數(shù)表列中的參數(shù),應(yīng)當(dāng)基類構(gòu)造函數(shù)和子對象的參數(shù)表列中的參數(shù)。基類構(gòu)造函數(shù)和子對象的次序可以是任意的,如上面的派生類構(gòu)造函數(shù)首部可以寫成Student1(int n, string nam,int n1, string nam1,int a, string ad): monitor(n1,nam1),Student(n,nnam)編譯系統(tǒng)是根據(jù)相同的參數(shù)名(而不是根據(jù)參數(shù)的順序)來確立它們的傳遞先寫基類構(gòu)造函數(shù)。如果有多個子對象,派生類構(gòu)造函數(shù)的寫法依此類的。但是習(xí)慣上一般11.5.3 多層派生時
49、的構(gòu)造函數(shù)一個類不僅可以派生出一個派生類,派生類還可以繼續(xù)派生,形成派生的層次結(jié)構(gòu)。在上面敘述的基礎(chǔ)上,不難寫出在多級派生情況下派生類的構(gòu)造函數(shù)。例11.7 多級派生情況下派生類的構(gòu)造函數(shù)。#include <iostream> #include<string> using namespace std;class Student/public:基類/公用部分/基類構(gòu)造函數(shù)Student(int n, string nnam)num=n; name=nam;void display( )/輸出基類數(shù)據(jù)成員cout<<num:<<num<<
50、;endl; cout<<name:<<name<<endl;protected: int num;string name;/保護(hù)部分/基類有兩個數(shù)據(jù)成員class Student1: public Studentpublic:/公用派生類Student1Student1(int n,char nnam10,iinta):Student(n,n, nam)/派生類構(gòu)造函數(shù)age=a; void show( )display( );/在此處只對派生類新增的數(shù)據(jù)成員初始化/輸出nnum,nnam和e aage/輸出num和namecout<<age:
51、 <<age<<eend;lprivate: int age;/派生類的私有數(shù)據(jù)/增加一個數(shù)據(jù)成員class Student2:public Student1public:/間接公用派生類Student2/下面是間接派生類構(gòu)造函數(shù)Student2(int n, string nam,int a,int s):Student1(n,nam,a)score=s;void show_all( )show( );/輸出全部數(shù)據(jù)成員/輸出num和namecout<<score:<<score<<endl;private:/輸出ageint sc
52、ore;/增加一個數(shù)據(jù)成員int main( )Student2 stud(10010,Li,17,89);stud.show_all( ); return 0;運行時的輸出如下:num:10010 name:Li age:17score:89/輸出學(xué)生的全部數(shù)據(jù)如圖11.13所示。其派生圖11.13請注意基類和兩個派生類的構(gòu)造函數(shù)的寫法:基類的構(gòu)造函數(shù)首部:Student(int n, string nam)派生類Student1的構(gòu)造函數(shù)首部:SStudent1i(nt n, string nnam,iinta):Student(n,nnam)派生類Student2的構(gòu)造函數(shù)首部:Stud
53、ent2(int n, string nam,int a,int s):Student1(n,nam,a)Student2類對象時,調(diào)用Student2構(gòu)造函在數(shù);在執(zhí)行Student2構(gòu)造函數(shù)時,先調(diào)用Student1 構(gòu)造函數(shù);在執(zhí)行Student1構(gòu)造函數(shù)時,先調(diào)用基類SStuden構(gòu)t造函數(shù)。初始化的順序是: 先初始化基類的數(shù)據(jù)成員num和name。 再初始化Student1的數(shù)據(jù)成員age。 最后再初始化Student2的數(shù)據(jù)成員score。11.5.4 派生類構(gòu)造函數(shù)的特殊形式在使用派生類構(gòu)造函數(shù)時,有以下特殊的形式:(1) 當(dāng)不需要對派生類新增的成員進(jìn)行任何初始化操作時,派生類構(gòu)造函數(shù)的函數(shù)體可以為空,即構(gòu)造函數(shù)是空函數(shù),如例11.6構(gòu)造函數(shù)可以改寫為派生類Student1Student1(int n, strin nam,iintn1, sstrinnam1):Student(n,nnam), monitor(n1,nam1) 此派生類構(gòu)造函數(shù)的作用只是參數(shù)傳遞給基類構(gòu)造函數(shù)和子對象,并在執(zhí)行派生類構(gòu)造函數(shù)時調(diào)用基類構(gòu)造函數(shù)和子對象構(gòu)造函數(shù)。在實際工作中常見這種用法。(2) 如果在基類中沒有定義構(gòu)造函數(shù),或定義了沒有參數(shù)的構(gòu)造函數(shù),那么在定義派生類
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 可再生能源電解水制氫耦合合成氨系統(tǒng)集成與技術(shù)經(jīng)濟(jì)評價
- 二零二五年度汽車維修保養(yǎng)套餐銷售代理居間服務(wù)合同
- 應(yīng)急預(yù)案落地實施
- 科技行業(yè)的會計工作總結(jié)
- 二零二五個人向金融機構(gòu)借款合同終止條件合同模板4篇
- 二零二五年度鋼構(gòu)橋梁建造與維護(hù)服務(wù)合同
- 游戲中心前臺工作心得
- 工業(yè)園區(qū)綜治工作中心上墻制度
- 二零二五版石料運輸車輛運輸責(zé)任保險合同范本6篇
- 進(jìn)出口行業(yè)客戶開發(fā)總結(jié)
- 2023學(xué)年廣東省深圳實驗學(xué)校初中部九年級(下)開學(xué)語文試卷
- 企業(yè)新員工培訓(xùn)師帶徒方案
- 2025屆河南省鄭州一中高三物理第一學(xué)期期末學(xué)業(yè)水平測試試題含解析
- 美容美發(fā)行業(yè)衛(wèi)生管理規(guī)范
- 個體工商戶章程(標(biāo)準(zhǔn)版)
- 河南省安陽市2024年中考一模語文試卷(含答案)
- 廢舊物資買賣合同極簡版
- TD/T 1044-2014 生產(chǎn)項目土地復(fù)墾驗收規(guī)程(正式版)
- 2024年湖南現(xiàn)代物流職業(yè)技術(shù)學(xué)院單招職業(yè)適應(yīng)性測試題庫及答案1套
- 垃圾桶創(chuàng)新設(shè)計說明書
- 2024年正定縣國資產(chǎn)控股運營集團(tuán)限公司面向社會公開招聘工作人員高頻考題難、易錯點模擬試題(共500題)附帶答案詳解
評論
0/150
提交評論