c++譚浩強教學第5章修訂.doc_第1頁
c++譚浩強教學第5章修訂.doc_第2頁
c++譚浩強教學第5章修訂.doc_第3頁
c++譚浩強教學第5章修訂.doc_第4頁
c++譚浩強教學第5章修訂.doc_第5頁
已閱讀5頁,還剩58頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第五章 繼承與派生51繼承與派生的概念(P150)一、為什么要使用繼承通過繼承的機制,可以利用已有的類來定義新的類,所定義的新類型擁有原來類型的屬性,同時還擁有新的屬性。繼承的目的在于實現(xiàn)代碼的重用。稱已存在用來生成新的類型的類為基類,而由已存在類派生出來的新類為派生類。派生類繼承了基類,即派生類中擁有基類中所有成員,并且派生類本身還擁有它自己的新成員。例如:已建有學生基本數(shù)據(jù)類 Studentclass Studentpublic: void display( ) coutnum: numendl; coutname: nameendl; coutsex: sexendl; private : int num; string name; char sex; 欲創(chuàng)建學生檔案類1 Student1class Student1public: void display( ) coutnum: numendl; coutname: nameendl; coutsex: sexendl; coutage: ageendl; coutaddress: addrendl; private : int num; string name; char sex;int age; string addr; 二、單繼承與多繼承一個派生類只有一個直接基類的情況,稱為單繼承,一個派生類同時有多個基類的情況,稱為多繼承。XYZABC 單繼承 多繼承5.2 派生類的聲明方式(P153)單繼承派生類的一般定義格式class 派生類名:繼承方式 基類名/派生類新增的數(shù)據(jù)成員和成員函數(shù)說明:(1)三種繼承方式:公有繼承:class Student1:public Student/.;私有繼承:class Student1: private Student/.;保護繼承:class Student1: protected Student/.;例如:class Student1:public Studentpublic: void display1( ) coutage: ageendl; coutaddress: addrendl; private : int age; string addr; 5.3 派生類的構(gòu)成(p154) 基類 派生類成員函數(shù)Student類int num;string name;char sex;void display();Student1類int num;string name;char sex;void display();int age;string addr;void display1();繼承新增數(shù)據(jù)成員1. 派生類繼承了基類的所有成員;2. 增加新的成員;3. 改變現(xiàn)有成員的屬性和重新定義基類中已有的成員函數(shù)。5.4 派生類成員的訪問屬性*基類成員在派生類中的訪問屬性三種不同的繼承方式導致原來具有不同訪問屬性的基類的成員在派生類中具有不同的訪問屬性。在基類中的訪問屬性繼承方式在派生類中的訪問屬性privatepublic不可直接訪問privateprivate不可直接訪問privateprotected不可直接訪問publicpublicpublicpublicprivateprivatepublicprotectedprotectedprotectedpublicprotectedprotectedprivateprivateprotectedprotectedprotected從表中歸納出:(1)基類中的私有成員無論哪種繼承方式,基類中的私有成員在派生類中都不可直接訪問;(2)基類中的公用成員當類的繼承方式為公用繼承時,基類中的所有公用成員在派生類中仍以公用成員的身份出現(xiàn);當類的繼承方式為私有繼承時,基類中的所有公用成員在派生類中都是以私有成員的身份出現(xiàn);當類的繼承方式為保護繼承時,基類中的所有公用成員在派生類中都是以保護成員的身份出現(xiàn)。(3)基類中的保護成員當類的繼承方式為公用繼承時,基類中的所有保護成員在派生類中仍以保護成員的身份出現(xiàn);當類的繼承方式為私有繼承時,基類中的所有保護成員在派生類中都是以私有成員的身份出現(xiàn);當類的繼承方式為保護繼承時,基類中的所有保護成員在派生類中仍以保護成員的身份出現(xiàn)。5.4.1 公用繼承公有繼承的特點是:基類的公有成員和保護成員作為派生類的成員時,它們都保持原有的狀態(tài),而基類的私有成員仍然是私有的,在派生類中是不可訪問的。例5.1 訪問公有基類的成員#include #include using namespace std;class Studentpublic: void get_value() cinnumnamesex; void display( ) coutnum: numendl; coutname: nameendl; coutsex: sexageaddr; void display_1() /coutnum: numendl; /企圖引用基類的私有成員,錯誤 /coutname: nameendl; /企圖引用基類的私有成員,錯誤 /coutsex: sexendl; /企圖引用基類的私有成員,錯誤 coutage: ageendl; /引用派生類的私有成員,正確 coutaddress: addrendl;/引用派生類的私有成員,正確 private: int age; string addr; ;int main() Student1 stud1; stud1.get_value(); stud1.get_value_1(); stud1.display(); stud1.display_1(); return 0;例:5.2 公有繼承的訪問規(guī)則#includeclass base /聲明一個基類public: void setxy(int m,int n) x=m; y=n; void showxy() coutx=xendl; couty=yendl; private: int x; protected: int y;class A:public base /聲明derived為base的公有派生類public: void setxyz(int m,int n,int l) setxy(m,n); /ok z=l; void showxyz() coutx=xendl; /error couty=yendl; /ok coutz=zendl; private: int z;main() A obj; obj.setxyz(30,40,50); obj.showxy(); /ok obj.setxy(20,30); obj.showxyz(); return 0;說明:(1) 在公有繼承時,基類中的公有成員和保護成員可以被派生類的成員函數(shù)訪問,基類中僅有公有成員才可被派生類的對象訪問;(2) 基類無論怎樣繼承,他的私有成員對派生類而言都是不能直接訪問的。表5.1 P1565.4.2 私有繼承(P158)私有繼承的特點是:每個成員,無論是public,protected還是private成員,在派生類中都是private成員,而且它們都不能再被派生類的子類所訪問。例5.3 P159例5.2#include #include using namespace std;class Studentpublic: void display( ) coutnum: numendl; coutname: nameendl; coutsex: sexendl; private : int num; string name; char sex; class Student1: private Studentpublic: void display_1() display(); coutage: ageendl; /引用派生類的私有成員,ok coutaddress:addrendl;/引用派生類的私有成員0k private: int age; string addr;int main() Student1 stud1;stud1.display(); /errorstud1.display_1(); /ok stud1.age=18; /errorreturn 0;說明:私有繼承時,派生類的成員函數(shù)可以訪問基類中的公有成員和保護成員;但派生類的對象不能訪問基類中的任何成員。例54 保護成員以私有方式被繼承后的訪問屬性#includeclass base /聲明一個基類public: void seta(int sa) a=sa; void showa() couta=aendl; protected: int a;class A:private base public: void setab(int sa,int sb) a=sa; b=sb; void showab() couta=aendl; coutb=bendl; protected: int b;class B:private A public: void setabc(int sa,int sb,int sc) setab(sa,sb); c=sc; void showabc() couta=aendl; /error 可改為:showab(); coutb=bendl; /ok coutc=cendl; private: int c;void main() base op1; op1.seta(1); op1.showa(); A op2; op2.setab(2,3); op2.showab(); B op3; op3.setabc(4,5,6); op3.showabc(); 注意:由于私有派生類限制太多,使用不方便,一般不常使用。5.43 保護成員和保護繼承的訪問規(guī)則(P161)保護繼承的特點是:基類的所有公有成員和保護成員都成為派生類的保護成員,并且只能被它的派生類成員函數(shù)或友元訪問,而基類的私有成員仍然是私有的。例55保護繼承的訪問規(guī)則#includeclass base /聲明一個基類public: int z; void setx(int i) x=i; int getx() return x; private: int x; protected: int y;class A:protected base public: int p; void setall(int a,int b,int c,int d,int e,int f);void show();private:int m;protected:int n;void A :setall(int a,int b,int c,int d,int e,int f) x=a; /error,可改為: setx(a); y=b; /ok z=c; /ok m=d; n=e; p=f;void A :show()coutx=xendl; /error coutx=getx()endl; /okcouty=yendl; /ok coutz=zendl; coutm=mendl; coutn=nendl; void main() A obj; obj.setall(1,2,3,4,5,6); obj.show(); coutp=obj.pendl; 表5.3 P161說明:保護成員和保護繼承方式的作用:三種繼承方式小結(jié):(1)閱讀P162表5.4 (2)閱讀P162P163l 在派生類中,成員有四種不同的訪問屬性;l 類的成員在不同作用域中有不同的訪問屬性。例 5.6(P163例5.3)在派生類中引用保護成員include #include using namespace std;class Student /聲明基類public: /基類公用成員 void display( ); protected : /基類保護成員 int num; string name; char sex;void Student:display( ) coutnum: numendl; coutname: nameendl; coutsex: sexendl;class Student1: protected Student /用protected繼承方式聲明一個派生類public: void display1( ); private: int age; string addr;void Student1:display1( )coutnum: numendl; /引用基類的保護成員,合法 coutname: nameendl;/引用基類的保護成員,合法 coutsex: sexendl; /引用基類的保護成員,合法 coutage: ageendl; /引用派生類的私有成員,合法 coutaddress:addrendl;/引用派生類的私有成員,okint main( ) Student1 stud1; /stud1是派生類student2的對象 stud1.display1( ); /display是派生類中的公用成員函數(shù) return 0; 5.4.4 多級派生時的訪問屬性 (P164)例5.7 (P164例5.4)多級派生時的訪問屬性class A /基類 public: int i; protected: void f2(); int j; private: int k;class B: public A /public方式 public: void f3( ); protected: void f4(); private: int m;class C: protected B /protected方式 public: void f5(); private: int n;if2jkf3f4mf5n基類A公用保護保護私有公用派生類B公用保護保護不可訪問公用保護私有保護派生類C保護保護保護不可訪問保護保護不可訪問公用私有從表中可以看出:l 在派生類C的外面,只能訪問C的成員函數(shù)f5;l 派生類C的成員函數(shù)f5能訪問基類A的成員i、f2、j和派生類B的成員f3,f4;l 派生類B的成員函數(shù)f3能訪問基類A的成員i、f2、j.問題:私有成員k,m,n能被誰訪問?結(jié)論:無論是哪一種繼承方式,在派生類中是不能訪問基類的私有成員,私有成員只能被本類的成員函數(shù)所訪問。55 派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)551 簡單的派生類的構(gòu)造函數(shù)的構(gòu)造原則(簡單的派生類:只有一個基類,只有一級派生,不包含子對象)簡單的派生類構(gòu)造函數(shù)的一般格式:派生類名(總參數(shù)表列):基類名(參數(shù)表列) 派生類中新增數(shù)據(jù)成員初始化語句 例5.8 (P167例5.5)簡單的派生類的構(gòu)造函數(shù)#include #includeusing namespace std;class Student /聲明基類public: /公用部分 Student(int n,string nam,char s ) /基類構(gòu)造函數(shù) num=n; name=nam; sex=s; Student( ) /基類析構(gòu)函數(shù) protected: /保護部分 int num; string name; char sex ; /基類析構(gòu)函數(shù);class Student1: public Student /聲明公用派生類studentpublic: Student1(int n,string nam,char s,int a,string ad ) : Student(n,nam,s) /派生類構(gòu)造函數(shù) age=a; /在函數(shù)體中只對派生類新增的數(shù)據(jù)成員初始化 addr=ad; void show( ) coutnum: numendl; coutname: nameendl; coutsex: sexendl; coutage: ageendl; coutaddress: addrendlendl; Student1( ) /派生類析構(gòu)函數(shù) private: /派生類的私有部分 int age; string addr; ;int main( ) Student1 stud1(10010,Wang-li,f,19,115 Beijing Road,Shanghai ); Student1 stud2(10011,Zhang-fun,m,21,213 Shanghai Road,Beijing ); stud1.show( ); /輸出第一個學生的數(shù)據(jù) stud2.show( ); /輸出第二個學生的數(shù)據(jù) return 0;說明:(1)在建立一個派生類對象時,執(zhí)行派生類構(gòu)造函數(shù)的順序為:先調(diào)用基類構(gòu)造函數(shù),再執(zhí)行派生類構(gòu)造函數(shù)本身;(2)在類中對派生類構(gòu)造函數(shù)僅作聲明時,不包括基類構(gòu)造函數(shù)名及其參數(shù)表列,只在類外定義函數(shù)時才將其列出;例如:類內(nèi)聲明:Student1(int n,string nam,char s,int a,string ad ) ;類外定義:Student1(int n,string nam,char s,int a,string ad ) : Student(n,nam,s) age=a; /在函數(shù)體中只對派生類新增的數(shù)據(jù)成員初始化 addr=ad;(3)派生類構(gòu)造函數(shù)也可采用參數(shù)列表的形式,例如:Student1(int n,string nam,char s,int a,string ad ) : Student(n,nam,s),age(a), addr(ad) 552 有子對象的派生類的構(gòu)造函數(shù)的構(gòu)造原則(P169)(有子對象的派生類: 新增的某個數(shù)據(jù)成員又是一個類的對象 )有子對象的派生類構(gòu)造函數(shù)的一般格式:派生類名(總參數(shù)表列):基類名(參數(shù)表列),子對象名(參數(shù)表列) 派生類中新增數(shù)據(jù)成員初始化語句 例5.9 (P170例5.6)包含子對象的派生類的構(gòu)造函數(shù)(在派生類Student1中增加“班長”一項,即學生數(shù)據(jù)中包含他們的班長的姓名和其他基本情況,而班長本身也是學生,屬于Student類)#include #include using namespace std;class Student /聲明基類 public: /公用部分 Student(int n,string nam) /基類構(gòu)造函數(shù) num=n; name=nam; void display() /輸出基類數(shù)據(jù)成員 coutnum:numendlname:nameendl; protected: /保護部分 int num; string name;class Student1: public Student/用public繼承方式聲明派生類studentpublic: Student1(int n,string nam,int n1,string nam1,int a,string ad) :Student(n,nam),monitor(n1,nam1)/派生類構(gòu)造函數(shù) age=a; /在此處只對派生類新增的數(shù)據(jù)成員初始化 addr=ad; void show( ) coutThis student is:endl; display(); /輸出num和name coutage: ageendl; coutaddress: addrendlendl; void show_monitor() /輸出子對象的數(shù)據(jù)成員 coutendlClass monitor is:endl; monitor.display(); /調(diào)用基類成員函數(shù) private: /派生類的私有數(shù)據(jù) Student monitor; /定義子對象(班長) int age; string addr; ;int main( ) Student1 stud1(10010,Wang-li,10001,Li-sun,19,115 Beijing Road,Shanghai); stud1.show( ); /輸出第一個學生的數(shù)據(jù)stud1.show_monitor(); /輸出子對象的數(shù)據(jù) return 0;說明:(1)在建立一個含有子對象的派生類對象時,執(zhí)行派生類構(gòu)造函數(shù)的順序為:l 調(diào)用基類構(gòu)造函數(shù),對基類數(shù)據(jù)成員初始化;l 調(diào)用子對象構(gòu)造函數(shù),對子對象數(shù)據(jù)成員初始化;l 再執(zhí)行派生類構(gòu)造函數(shù)本身,對派生類新增數(shù)據(jù)成員初始化(2)派生類構(gòu)造函數(shù)的總參數(shù)表列中的參數(shù),應當包括基類構(gòu)造函數(shù)和子對象的參數(shù)表列中的參數(shù);(3)如果有多個子對象,則在派生類構(gòu)造函數(shù)中應列出每一個子對象名及其參數(shù)表列。553 多層派生類時的構(gòu)造函數(shù)每一層派生類的構(gòu)造函數(shù)只需列出直接基類的構(gòu)造函數(shù)即可。例5.10(P172例5.7)多級派生情況下派生類的構(gòu)造函數(shù)#include #includeusing namespace std;class Student /聲明基類public: /公用部分 Student(int n, string nam ) /基類構(gòu)造函數(shù) num=n; name=nam; void display() /輸出基類數(shù)據(jù)成員 coutnum:numendl; coutname:nameendl; protected: /保護部分 int num; /基類有兩個數(shù)據(jù)成員 string name;class Student1: public Student /聲明公用派生類Student1public: /下面是派生類構(gòu)造函數(shù) Student1(int n,string nam,int a):Student(n,nam) age=a; /在此處只對派生類新增的數(shù)據(jù)成員初始化 void show( ) /輸出num,name和age display(); /輸出num和name coutage: ageendl; private: /派生類的私有數(shù)據(jù) int age; /增加一個數(shù)據(jù)成員;class Student2:public Student1 /聲明間接公用派生類student2public: /下面是間接派生類構(gòu)造函數(shù) Student2(int n,string nam,int a,int s):Student1(n,nam,a) score=s; void show_all() /輸出全部數(shù)據(jù)成員 show(); /輸出num和name coutscore:scoreendl; /輸出age private: int score; /增加一個數(shù)據(jù)成員 ;int main( ) Student2 stud(10010,Li,17,89); stud.show_all( ); /輸出學生的全部數(shù)據(jù) return 0;分析:建立Student2派生類對象stud的構(gòu)造函數(shù)執(zhí)行順序。調(diào)用:Student(n,nam);初始化基類數(shù)據(jù)成員num,name; 調(diào)用:Student1(n,nam,a);初始化Student1類中的數(shù)據(jù)成員age;再初始化Student2類中的數(shù)據(jù)成員score。554 派生類構(gòu)造函數(shù)的特殊形式(P175) 閱讀:P175554 派生類的析構(gòu)函數(shù)(P175)例511基類和派生類構(gòu)造函數(shù)和析構(gòu)函數(shù)的執(zhí)行順序#includeclass basepublic: base() cout基類的構(gòu)造函數(shù)endl; base() cout基類的析構(gòu)函數(shù)endl; ;class derive:public base public: derive() cout派生類的構(gòu)造函數(shù)endl; derive() cout派生類的析構(gòu)函數(shù)endl; ;main() derive op; return 0;說明:構(gòu)造函數(shù)的執(zhí)行順序:基類構(gòu)造函數(shù)-子對象類構(gòu)造函數(shù)(如果有子對象類)-派生類構(gòu)造函數(shù)析構(gòu)函數(shù)的執(zhí)行順序: 派生類構(gòu)造函數(shù)-子對象類構(gòu)造函數(shù)(如果有子對象類)-基類構(gòu)造函數(shù)56 多繼承(P176)561 多繼承的聲明多繼承與單繼承的區(qū)別僅在于它們基類的個數(shù),有兩個或兩個以上的基類的派生類稱為多繼承派生類。例如: 玩具車玩具車多繼承派生類的定義一般格式:class 派生類名:繼承方式1 基類名1,。繼承方式n 基類名n/派生類新增的數(shù)據(jù)成員和函數(shù)成員注:多繼承的訪問規(guī)則與單繼承相同例:5.12 多繼承情況下的訪問特性#includeclass Apublic: void setA(int x) a=x; void printA() couta=aendl; private: int a;class Bpublic: void setB(int x) b=x; void printB( ) coutb=bendl; private: int b;class C: public A,private Bpublic: void setC(int x,int y) c=x; setB(y); void printC() printB(); coutc=cendl; private: int c;int main() C obj; obj.setA(3); obj.printA(); obj.setB(4); /error C對B是私有繼承 obj.printB(); /error C對B是私有繼承 obj.setC(6,8); obj.printC(); return 0;562 多繼承派生類的構(gòu)造函數(shù)與析構(gòu)函數(shù)1 多繼承的構(gòu)造函數(shù)的一般形式派生類名(參數(shù)總表):基類名1(參數(shù)表1),基類名2(參數(shù)表2),。基類名n(參數(shù)表n)/派生類新增數(shù)據(jù)成員的初始化語句說明:多繼承派生類的構(gòu)造函數(shù)與單繼承派生類的構(gòu)造函數(shù)相似,它必須同時負責該派生類所有基類構(gòu)造函數(shù)的調(diào)用,同時,派生類的參數(shù)個數(shù)必須包含完成所有基類初始化所需的參數(shù)個數(shù)。例513 多繼承中構(gòu)造函數(shù)的定義方法#includeclass base1public: base1(int sx) /基類base1的構(gòu)造函數(shù) x=sx; int getx() return x; private: int x;class base2public: base2(int sy) /基類base1的構(gòu)造函數(shù) y=sy; int gety() return y; private: int y;class derived:public base1,private base2 public: derived(int sx,int sy,int sz):base1(sx),base2(sy) z=sz ; int getz() return z; int gety() return base2:gety(); private: int z;int main() derived obj(1,3,5); int ma=obj.getx(); coutx=maendl; int mb=obj.gety(); couty=mbendl; int mc=obj.getz(); coutz=mcendl; return 0; 例514(P176例5.8) 多繼承的應用#include #include using namespace std;class Teacher /聲明Teacher(教師)類public: /公用部分 Teacher(string nam,int a,string t)/構(gòu)造函數(shù) name=nam; age=a;title=t; /職稱 void display() /輸出教師有關(guān)數(shù)據(jù) coutname:nameendl; coutageageendl; couttitle:titleendl; protected: /保護部分 string name; int age; string title; /職稱;class Student /聲明類Student(學生)public: Student(string nam,char s,float sco) name1=nam; sex=s; score=sco; /構(gòu)造函數(shù) void display1() /輸出學生有關(guān)數(shù)據(jù) coutname:name1endl; coutsex:sexendl; coutscore:scoreendl; protected: /保護部分 string name1; char sex; float score; /成績 ;class Graduate:public Teacher,public Student /聲明多重繼承的派生類Graduate研究生public: /聲明多重繼承的派生類Graduate的構(gòu)造函數(shù) Graduate(string nam,int a,char s,string t,float sco,float w): Teacher(nam,a,t),Student(nam,s,sco),wage(w) void show( ) /輸出人員的有關(guān)數(shù)據(jù) coutname:nameendl; coutage:ageendl; coutsex:sexendl; coutscore:scoreendl; couttitle:titleendl; coutwages:wageendl; private: float wage; /工資;int main( ) Graduate grad1(Wang-li,24,f,assistant,89.5,1234.5); grad1.show( ); return 0;2多繼承的構(gòu)造函數(shù)與析構(gòu)函數(shù)的執(zhí)行順序先執(zhí)行所有基類的構(gòu)造函數(shù),再執(zhí)行派生類本身的構(gòu)造函數(shù),包含子對象在內(nèi),其中,多個基類構(gòu)造函數(shù)的執(zhí)行順序取決于定義派生類時所指定的多個基類的順序。析構(gòu)函數(shù)的執(zhí)行順序則與構(gòu)造函數(shù)的執(zhí)行順序相反。563 多繼承的“二義性”問題當兩個或多個基類中有相同的成員名稱時,即出現(xiàn)了“二義性”問題,編譯器將無法理解使用的是哪個成員。例515:多繼承中的“二義性”問題#includeclass father public:void disp() cout”姓名:李明“endl;class mo

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論