C++課件C++_第九章_第1頁
C++課件C++_第九章_第2頁
C++課件C++_第九章_第3頁
C++課件C++_第九章_第4頁
C++課件C++_第九章_第5頁
已閱讀5頁,還剩41頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1,第9章 繼承與派生,9.1 類的層次與繼承性 9.2 派生類 9.3 派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù) 9.4 多重繼承 9.5 賦值兼容 9.6 派生類的編程原則 9.7 小結(jié),2,9.1 類的層次與繼承性,繼承是描述類的層次性的機制,繼承的過程稱為派生。 派生類(也稱子類)繼承它父類的屬性和操作。子類也聲明了新的屬性和新的操作。,3,4,/person類 (人): class person private : char name10; int age; char sex; public: void showinfo( ); ;,/ employee類 (職員) : class employee private : char name10; int age; char sex; char department20; float salary; public: void showinfo( ); ;,5,9.2 派生類,9.2.1 派生類的聲明 已有的類稱為基類,由基類繼承而來的類稱為派生類。 C+中派生類定義的一般形式是: class 派生類名 : 派生方式 基類名 派生類新增加數(shù)據(jù)成員; 派生類新增加成員函數(shù); ;,6,其中: 派生方式關(guān)鍵字為private、public或protected,分別表示私有繼承、公有繼承和保護繼承。缺省的繼承方式(即沒有顯示聲明)是私有繼承。 派生類成員是指除了從基類繼承來的成員外,新增加了數(shù)據(jù)成員和成員函數(shù)。通過新增加成員來實現(xiàn)代碼的復用和功能的擴充。,7,說明: 1.派生方式有private、public或protected 2.基類(或父類)和派生類(子類) 3.直接基類和間接基類 4.派生類具有的成員 5.派生和繼承是同一個問題的不同表述 class A int a; ; class B:public A int b; ,8,通過繼承和派生改寫employee class person private : char name10; int age; char sex; public: void showinfo( ); ;,class employee :public person private : char department20; float salary; ;,9,9.2.2 派生類的訪問控制權(quán)限 注意:類的不可訪問成員不能被任何函數(shù)訪問,可以被繼承傳遞下去,10,class A private: int s; public: void inits(int n) s=n; int gets( ) return s; void sets(int a) s=a; ;,class B: public A private: int t; public: void initt(int n) t=n; int getts( ) return t*gets(); void sett(int a) t=a; ;,11,void main( ) B ob; ob.sets(12); ob.sett(5); coutob.getts( )endl; 一定要熟練掌握繼承方式,12,派生類生成過程(派生類的編程步驟),吸收基類成員,改造基類成員,發(fā)展新成員,重寫構(gòu)造函數(shù)與析構(gòu)函數(shù),全盤接收父類成員(除構(gòu)造函數(shù)與析構(gòu)函數(shù)),添加和父類同名成員,即覆蓋(override),添加新的與父類成員不同名的成員,13,9.3.1 派生類構(gòu)造函數(shù)和析構(gòu)函數(shù)的執(zhí)行順序 對于創(chuàng)建對象,先執(zhí)行基類的構(gòu)造函數(shù),再執(zhí)行派生類中對象成員的構(gòu)造函數(shù),最后執(zhí)行派生類的構(gòu)造函數(shù)。 對于釋放對象,先執(zhí)行派生類的析構(gòu)函數(shù),再執(zhí)行派生類中對象成員的析構(gòu)函數(shù),最后執(zhí)行基類的析構(gòu)函數(shù)。,9.3 派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù),14,9.3.2派生類構(gòu)造函數(shù)和析構(gòu)函數(shù)的設(shè)計 派生類構(gòu)造函數(shù)和析構(gòu)函數(shù)設(shè)計的原則 如果基類定義了帶有形參表的構(gòu)造函數(shù),派生類就必須定義新的構(gòu)造函數(shù),提供一個將參數(shù)傳遞給基類構(gòu)造函數(shù)的途徑,以便保證在基類進行初始化時能獲得必需的數(shù)據(jù)。 如果派生類的基類也是派生類,則每個派生類只需負責其直接基類的構(gòu)造,不負責自己的間接基類的構(gòu)造。 派生類是否要定義析構(gòu)函數(shù)與所屬的基類無關(guān),如果派生類對象在撤銷時需要做清理善后工作,就需要定義新的析構(gòu)函數(shù)。,15,2. 派生類構(gòu)造函數(shù)的設(shè)計 派生類名派生類名(參數(shù)總表):基類名(參數(shù)表),新增對象成員名1(參數(shù)表1),新增對象成員名n(參數(shù)表n) /派生類新增成員的初始化語句 派生類的構(gòu)造函數(shù)負責類內(nèi)所有成員的構(gòu)造,16,3. 派生類析構(gòu)函數(shù)的設(shè)計 派生類析構(gòu)函數(shù)的功能與基類析構(gòu)函數(shù)的功能一樣,也是在對象撤銷時進行必需的清理善后工作。析構(gòu)函數(shù)不能被繼承,如果需要,則要在派生類中重新定義。與基類的析構(gòu)函數(shù)一樣,派生類的析構(gòu)函數(shù)也沒有數(shù)據(jù)類型和參數(shù)。 派生類析構(gòu)函數(shù)的定義的方法與基類的析構(gòu)函數(shù)的定義方法完全相同,函數(shù)體只需完成對派生類新增成員的清理和善后就行了,基類和對象成員的清理善后工作系統(tǒng)會自動調(diào)用他們各自的析構(gòu)函數(shù)來完成。,17,class A int x; public: A(int n=0) cout“構(gòu)造A:“nendl; x=n; ; class B:public A int y; public: B(int m,int n):A(n) cout“構(gòu)造B:“mendl; y=m; B( )cout“構(gòu)造B“endl; ; void main( ) B b1(1,2), b2; ,18,class A1 int a1; ; class A2 int a2; public: A2( ) a2=0; A2(int n) a2=n; ; class B1:public A1 int b1; ;,class B2:public A2 int b2; public: B2(int m,int n):A2(n) b2 = m; B2( ) b2=1; ; void main( ) B1 obj1; /? B2 obj2; /? B2 obj3(1,2); /? ,基類里沒有定義構(gòu)造函數(shù),則由系統(tǒng) 提供默認的構(gòu)造函數(shù),19,class A public: A(int a) cout“構(gòu)造A:“ aendl; ; class B public: B(int b) cout“構(gòu)造B:“ bendl; ;,class C:public A B m_b; public: C(int a,int b):A(a),m_b(b) cout“構(gòu)造C“ endl; ; void main( ) C cObj(1,2); ,派生類含有子對象時,在派生類的構(gòu)造函數(shù)中要給 出初始化形式,若沒給出,則調(diào)用默認構(gòu)造函數(shù),20,class A int a; public: A(int a1)a=a1; ; class B:public A int b; public: B(int b1,int a1):A(a1) b=b1; ;,class C:public B int c; public: C(int c1,int b1,int a1) :B(b1,a1) c=c1; C( ) /? ; void main( ) C c(1,2,3); ,多層派生中各層的構(gòu)造函數(shù), 一般子類只向其直接父類負責,21,派生類對象析構(gòu)順序:先派生類后基類(重點),class A int x; public: A( ) cout“構(gòu)造A“endl; A( ) cout“析構(gòu)A“endl; ; class B:public A int y; public: B( ) cout“構(gòu)造B“endl; B( ) cout“析構(gòu)B“endl; ;,void main( ) A a1 B b1; ,a1,x,b1,x,y,22,class A int x; public: A(int a) x=a; cout“構(gòu)造A:“xendl; A( )cout“析構(gòu):A“xendl; ; class B:public A int y; public: B(int a,int b):A(a) y=b; cout“構(gòu)造B:“yendl; B( )cout“析構(gòu)B:“yendl; ;,void main( ) A a1(0) B b1(1,2); B b2(3,4); ,23,class A int x; public: A(int a)x=a; cout“構(gòu)造A:“ xendl; A( )cout“析構(gòu)A:“ xendl; ; class B int y; public: B(int b)y=b; cout“構(gòu)造B:“ yendl;,B( )cout“析構(gòu)B:“ yendl; ; class C:public A B m_b; public: C(int a,int b):A(a),m_b(b) cout“構(gòu)造C:“endl; C( )cout“析構(gòu)C:“ endl; ; void main( )C objC(1,2);,一定弄清楚本例,24,9.4 多重繼承,9.4.1 多重繼承的概念 當一個派生類具有多個基類時,稱這種派生為多重繼承或多基派生。在多繼承中,派生類擁有了所有父類成員。 多重繼承聲明的一般形式為: class 派生類名:派生方式1 基類名1,派生方式n 基類名n 派生類成員聲明; ; 其中,冒號后面的部分稱為基類表,之間用逗號分開。,25,class base1 public: int x; int a( ); int b( ); int b(int); int c( ); ; class base2 int x; int a( );,public: float b(); int c(); ; class derived:public base1, public base2 ; void main( ) derived e; e.x=10; /錯誤,二義性 e.a( ); /錯誤,二義性 e.b( ); /錯誤,二義性 e.c( ); /錯誤,二義性 ,26,多種繼承中的主要問題是標識不唯一,解決辦法 : 1. 使用作用域運算符 如果派生類的基類之間沒有繼承關(guān)系,同時又沒有共同的基類,則在引用同名成員時,可在成員名前加上類名和作用域運算符“”,來區(qū)別來自不同基類的成員。 void main( ) derived e; e.base1:x=10; e.base2:a(); e.base2:b(); e.base1:c(); ,27,2. 使用同名覆蓋的原則 在派生類中重新定義與基類中同名的成員(如果是成員函數(shù),則參數(shù)表也要相同,參數(shù)不同的情況為重載)以隱蔽掉基類的同名成員,在引用這些同名的成員時,使用的就是使用派生類中的函數(shù),也就不會出現(xiàn)二義性的問題了。,28,9.4.2 多重繼承的構(gòu)造函數(shù)和析構(gòu)函數(shù) 多重繼承時,也涉及到基類成員、對象成員和派生類成員的初始化問題。 聲明多繼承構(gòu)造函數(shù)的一般形式為: 派生類名派生類名(參數(shù)總表)基類名1(參數(shù)表1),基類名n(參數(shù)表n),對象成員名1(對象成員參數(shù)表1),對象成員名m(對象成員參數(shù)表m) /派生類新增成員的初始化語句 ,29,其中: 派生類的構(gòu)造函數(shù)名與派生類名相同。 參數(shù)總表列出初始化基類成員數(shù)據(jù)、新增對象成員數(shù)據(jù)和派生類新增成員數(shù)據(jù)所需要的全部參數(shù)。 冒號后列出需要使用參數(shù)進行初始化的所有基類的名字和所有對象成員的名字及各自的參數(shù)表,之間用逗號分開。對于使用缺省構(gòu)造函數(shù)的基類或?qū)ο蟪蓡T,可以不給出類名或?qū)ο竺约皡?shù)表。,30,class A int m_a; public: A( ) m_a=0; int GetA( )return m_a; ; class B protected: int m_b; public: B( ) m_b=1; int GetB( )return m_b; ;,class C:public A int m_c; public: C( )m_c=2; ;,31,class D:public A,protected B int m_d; public: D( )m_d=2; ; void main( ) C c; D d; coutc.GetA( )endl;/? coutd.GetA( )endl;/? coutsizeof(c)endl;/? coutsizeof(d)endl;/? coutc.GetB( )endl;/? coutd.GetB( )endl;/? ,32,m_a,m_b,m_c,m_d,GetA,GetB,m_a,GetA,m_a,m_b,GetA,GetB,public,public,protected,私有,保護,公有,不可訪問,A類,B類,C類,D類,33,/找出錯誤代碼的地方 class A int a1; protected: int a2; public: int a3; class B:protected A int b; void f1( ) a1+; public: void f2( ) a2+; protected: void f3( ) a3+; ;,class C:public B public: void ShowC( ) b+; a1+; a2+; a3+; fun1( ); fun2( ); fun3( ); ;,34,9.4.3 虛基類 1. 虛基類的概念 多繼承中,要引用派生類的成員時,先是在派生類自身的作用域內(nèi)尋找,若找不到,再到基類中尋找,這時,如果這些基類又有一個共同的基類,派生類訪問這個公共的成員時,就有可能由于同名成員的問題而發(fā)生二義性。 2. 虛基類的定義 虛基類的聲明是在派生類的聲明過程中進行的,一般形式為: class 派生類名:virtual 派生方式 基類名,35,在一個類的繼承過程中使用virtual修飾后,則虛基類的成員在進一步派生過程中和派生類一起維護同一個內(nèi)存拷貝,避免了二義性。 3. 虛基類的構(gòu)造函數(shù)和初始化 虛基類的初始化與一般的多繼承的初始化在語法上是一樣的,但構(gòu)造函數(shù)的執(zhí)行順序不同: (1)虛基類的構(gòu)造函數(shù)的執(zhí)行在非虛基類的構(gòu)造函數(shù)之前。 (2)在派生類的構(gòu)造函數(shù)的初始化列表給出了虛基類的構(gòu)造形式。,36,class base protected: int x; public: base() x=1; base(int x1) x=x1; ; class base1:virtual public base public: base1():base(2) cout“constructing base1,x=“xendl; ;,37,class base2:virtual public base public: base2() cout“constructing base2,x=“xendl; ; class derived:public base2,public base1 public: derived():base(3) cout“constrcting derived x=“xendl; ; void main() derived obj; ,38,9.5 賦值兼容,賦值兼容規(guī)則是指在需要基類對象的任何地方都可以使用公有派生類的對象來替代。通過公有繼承,派生類得到了基類中除構(gòu)造函數(shù)、析構(gòu)函數(shù)之外的所有成員,而且所有成員的訪問控制屬性也和基類完全相同。公有派生類實際就具備了基類的所有功能,凡是基類能解決的問題,公有派生類都可以解決。 賦值兼容規(guī)則中所指的替代包括以下的情況: 派生類的對象可以賦值給基類對象。 派生類的對象可以初始化基類的引用。 派生類對象的地址可以賦給指向基類的指針。,39,class B0 public: void display( ) cout“B0:display()“endl; ; class B1:public B0 public: void display( ) cout“Bi:display()“endl; ; class D1:public B1 public: void display() cout“D1:display()“endl; ;,40,void fun1(B0 *ptr) ptr-display(); void fun2(B0 ,p= ,41,9.6 派生類的編程原則,派生類生成過程(派生類的編程步驟),吸收基類成員,改造基類成員,發(fā)展新成員,重寫構(gòu)造函數(shù)與析構(gòu)函數(shù),全盤接收父類成員(除構(gòu)造函數(shù)與析構(gòu)函數(shù)),添加和父類同名成員,即覆蓋(override),添加新的與父類成員不同名的成員,42,class Shape protected: int x,y;/原始點 public: Shape() x=y=0; Shape(int a,int b) x=a; y=b; ;,43,class Rectangle:public Shape protected: int x1,y1; public: Rectangle() x1=y1=0; Rectangle(int x,int y,int x1,int y1):Shape(x,y) this-x1=x1; this-y1=y1; int GetArea() return (x1-x)*(y1-y); ;,44,class Square:public Rectangle public: Square() Square(int length) x1=

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論