C++程序設計(譚浩強完整版)-繼承和派生類_第1頁
C++程序設計(譚浩強完整版)-繼承和派生類_第2頁
C++程序設計(譚浩強完整版)-繼承和派生類_第3頁
C++程序設計(譚浩強完整版)-繼承和派生類_第4頁
C++程序設計(譚浩強完整版)-繼承和派生類_第5頁
已閱讀5頁,還剩125頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、1第十一章 繼承和派生類2繼承性是面向對象程序設計中最重要的機制。繼承性是面向對象程序設計中最重要的機制。這種機制這種機制提供了無限重復利用程序資源的一提供了無限重復利用程序資源的一種途徑種途徑。通過。通過C+語言中的繼承機制,語言中的繼承機制,可以可以擴充和完善舊的程序設計以適應新的需求。擴充和完善舊的程序設計以適應新的需求。這樣不僅可以節(jié)省程序開發(fā)的時間和資源,這樣不僅可以節(jié)省程序開發(fā)的時間和資源,并且為未來程序增添了新的資源。并且為未來程序增添了新的資源。3class Student int num; char name30; char sex; public: void display

2、( ) /對成員函數(shù)對成員函數(shù)display的定義的定義 coutnum: numendl; coutname: nameendl; coutsex: sexendl; ;4class Studend1 int num; /此行原來己有此行原來己有 char name20; /此行原來己有此行原來己有 char sex; /此行原來己有此行原來己有 int age; char addr20; public: void display( ) ; /此行原來己有此行原來己有 coutnum: numendl; /此行原來己有此行原來己有 coutname: nameendl;/此行原來己有此行原來

3、己有 coutsex: sexendl; /此行原來己有此行原來己有 coutage: ageendl; coutaddress: addrendl; ; 5利用原來定義的類利用原來定義的類StudentStudent作為基礎,再加上新的作為基礎,再加上新的內(nèi)容即可,以減少重復的工作量。內(nèi)容即可,以減少重復的工作量。 C+C+提供的繼提供的繼承機制就是為了解決這個問題。承機制就是為了解決這個問題。 在在C+中所謂中所謂“繼承繼承”就是在一個已存在的類的基就是在一個已存在的類的基礎上建立一個新的類。礎上建立一個新的類。已存在的類稱為已存在的類稱為“基類基類(base class)”或或“父類父類

4、(father class)”。新建立的類。新建立的類稱為稱為“派生類派生類(derived class)”或或“子類子類(son class)”。 6class Student1: public Student/聲明基類是聲明基類是Studentprivate: int age; /新增加的數(shù)據(jù)成員新增加的數(shù)據(jù)成員 string addr; /新增加的數(shù)據(jù)成員新增加的數(shù)據(jù)成員public: void display_1( ) /新增加的成員函數(shù)新增加的成員函數(shù) coutage: ageendl; coutaddress: addrendl; ;7類類A派生類派生類B:類:類A為基類,類為基類

5、,類B為派生類。為派生類。AB新增加的成員數(shù)新增加的成員數(shù)據(jù)和成員函數(shù)據(jù)和成員函數(shù)8在在C+語言中,語言中,一個派生類可以從一個基類一個派生類可以從一個基類派生,也可以從多個基類派生。派生,也可以從多個基類派生。從一個基類從一個基類派生的繼承稱為單繼承;從多個基類派生的派生的繼承稱為單繼承;從多個基類派生的繼承稱為多繼承。繼承稱為多繼承。9通過繼承機制,可以利用已有的數(shù)據(jù)類型來通過繼承機制,可以利用已有的數(shù)據(jù)類型來定義新的數(shù)據(jù)類型。定義新的數(shù)據(jù)類型。所定義的新的數(shù)據(jù)類型所定義的新的數(shù)據(jù)類型不僅擁有新定義的成員,而且還同時擁有舊不僅擁有新定義的成員,而且還同時擁有舊的成員。的成員。我們稱已存在的

6、用來派生新類的類我們稱已存在的用來派生新類的類為基類,又稱為父類。為基類,又稱為父類。由已存在的類派生出由已存在的類派生出的新類稱為派生類,又稱為子類。的新類稱為派生類,又稱為子類。10在建立派生類的過程中,基類不會做任何改在建立派生類的過程中,基類不會做任何改變,變,派生類則除了繼承基類的所有可引用的派生類則除了繼承基類的所有可引用的成員變量和成員函數(shù)外,還可另外定義本身成員變量和成員函數(shù)外,還可另外定義本身的成員變量和處理這些變量的函數(shù),的成員變量和處理這些變量的函數(shù),由于派由于派生類可繼承基類的成員變量和成員函數(shù),因生類可繼承基類的成員變量和成員函數(shù),因此在基類中定義好的數(shù)據(jù)和函數(shù)等的程

7、序代此在基類中定義好的數(shù)據(jù)和函數(shù)等的程序代碼可重復使用,這樣可以提高程序的可靠性。碼可重復使用,這樣可以提高程序的可靠性。11當從已有的類中派生出新的類時,可以對派生類做以下幾當從已有的類中派生出新的類時,可以對派生類做以下幾種變化:種變化:1、 可以繼承基類的成員數(shù)據(jù)或成員函數(shù)??梢岳^承基類的成員數(shù)據(jù)或成員函數(shù)。2、可以增加新的成員變量。、可以增加新的成員變量。3、可以增加新的成員函數(shù)。、可以增加新的成員函數(shù)。4、可以重新定義已有的成員函數(shù)。、可以重新定義已有的成員函數(shù)。5、可以改變現(xiàn)有的成員屬性。、可以改變現(xiàn)有的成員屬性。在在C+中有二種繼承:單一繼承和多重繼承。當一個派生中有二種繼承:單

8、一繼承和多重繼承。當一個派生類僅由一個基類派生時,稱為單一繼承;而當一個派生類類僅由一個基類派生時,稱為單一繼承;而當一個派生類由二個或更多個基類所派生時,稱為多重繼承。由二個或更多個基類所派生時,稱為多重繼承。12類類A派生類派生類B:類:類A為基類,類為基類,類B為派生類。為派生類。AB但派生并不是簡單的擴充,有可能改變基類的性質。但派生并不是簡單的擴充,有可能改變基類的性質。有三種派生方式:公有派生、保護派生、私有派生。有三種派生方式:公有派生、保護派生、私有派生。class B:public A.; class B:protected A.; class B:private A.; 默

9、認的是私有派生。默認的是私有派生。class B: A .; A為私有派生為私有派生13從一個基類派生一個類的一般格式為:從一個基類派生一個類的一般格式為:class ClassName:BaseClassName private: .; /私有成員說明私有成員說明 public: .; /公有成員說明公有成員說明 protected: .; /保護成員說明保護成員說明 派生類名派生類名基類名基類名繼承方式繼承方式public: 表示公有基類表示公有基類private:表示私有基類表示私有基類(默認默認)protected:表示保護基類表示保護基類派生類中新增加的成員派生類中新增加的成員14公

10、有派生class ClassName: public BaseClassName公有派生時,公有派生時,基類中所有成員在派生類中保持各個成員的訪問權限基類中所有成員在派生類中保持各個成員的訪問權限。公有派生,派生類中保持基類的成員特性公有派生,派生類中保持基類的成員特性基類成員屬性基類成員屬性派生類中派生類中派生類外派生類外公有公有可以引用可以引用可以引用可以引用保護保護可以引用可以引用不可引用不可引用私有私有不可引用不可引用不可引用不可引用基類:基類:public: 在派生類和類外可以使用在派生類和類外可以使用protected: 在派生類中使用在派生類中使用private: 不能在派生類中

11、使用不能在派生類中使用15x(私有私有)y(保護保護)z(公有公有)A( )Getx()Gety()ShowA()Ax(私私有私私有)y(保護保護)z(公有公有)A( )Getx()Gety()ShowA()Bm(私有私有)n(私有私有)B()Show()Sum()publicx在類在類B新增加的成員中不能直新增加的成員中不能直接調(diào)用接調(diào)用y在類在類B中可以調(diào)用中可以調(diào)用z在整個文件中可以調(diào)用在整個文件中可以調(diào)用對類對類B的對象初始化即是對的對象初始化即是對x,y,z,m,n等全部成員的初始化等全部成員的初始化16class A int x;protected: int y;public: i

12、nt z; A(int a,int b,int c)x=a;y=b;z=c;/基類初始化基類初始化 int Getx()return x;/返回返回x int Gety()return y;/返回返回y void ShowA()cout x=xty=ytz=zn;class B:public Aint m,n;public: B(int a,int b,int c,int d,int e):A(a,b,c)m=d;n=e; void Show()cout“m=mt“n=nn; coutx=Getx()ty=ytz=zn; int Sum()return ( Getx()+y+z+m+n); ;

13、void main(void) B b1(1,2,3,4,5); b1.ShowA(); b1.Show(); cout Sum=b1.Sum()n;coutx=b1.Getx()t; cout y= b1.Gety()t;cout z=b1.zn;公有派生公有派生對基類初始化對基類初始化因為因為x是基類私有,所以在派生類和類外中不能直接引用是基類私有,所以在派生類和類外中不能直接引用因為因為y是基類保護,所以在是基類保護,所以在派生類中可以直接引用。而派生類中可以直接引用。而在類外不可直接引用。在類外不可直接引用。因為因為z是基類公有,是基類公有,所以在派生類中和類所以在派生類中和類外均可直

14、接引用。外均可直接引用。17私有派生class ClassName: private BaseClassName私有派生時,基類中公有成員和保護成員在派生類中均變?yōu)樗接械?,私有派生時,基類中公有成員和保護成員在派生類中均變?yōu)樗接械?,在派生類中仍可直接使用這些成員,在派生類中仍可直接使用這些成員,基類中的私有成員,在派生類基類中的私有成員,在派生類中不可直接使用。中不可直接使用。私有派生,派生類中基類公有和保護成員成為私有私有派生,派生類中基類公有和保護成員成為私有基類成員屬性基類成員屬性派生類派生類派生類外派生類外公有公有可以引用可以引用不可引用不可引用保護保護可以引用可以引用不可引用不可引用

15、私有私有不可引用不可引用不可引用不可引用基類:基類:public: (變?yōu)樗接凶優(yōu)樗接?在派生類中使用,類外不可使用在派生類中使用,類外不可使用protected: (變?yōu)樗接校┰谂缮愔惺褂?,類外不可使用變?yōu)樗接校┰谂缮愔惺褂?,類外不可使用private: 不能在派生類中和類外使用不能在派生類中和類外使用18x(私有私有)y(保護保護)z(公有公有)A( )Getx()Gety()ShowA()Ax(私私有私私有)y(私有私有)z(私有私有)A( )Getx()Gety()ShowA()Bm(私有私有)n(私有私有)B()Show()Sum()privatex在類在類B新增加的成員中新增加

16、的成員中不能直接調(diào)用不能直接調(diào)用y在類在類B中可以調(diào)用中可以調(diào)用z在類在類B中可以調(diào)用中可以調(diào)用對類對類B的對象初始化即是對的對象初始化即是對x,y,z,m,n等全部成員的初始化等全部成員的初始化均為私有均為私有類類B 外不外不能引用能引用19class A int x;protected: int y;public: int z; A(int a,int b,int c)x=a;y=b;z=c;/基類初始化基類初始化 int Getx()return x;/返回返回x int Gety()return y;/返回返回y void ShowA()cout x=xty=ytz=zn;class

17、B:private Aint m,n;public: B(int a,int b,int c,int d,int e):A(a,b,c)m=d;n=e; void Show()cout“m=mt“n=nn; coutx=Getx()ty=ytz=zn; int Sum()return ( Getx()+y+z+m+n); ;void main(void) B b1(1,2,3,4,5); b1.ShowA(); b1.Show(); cout Sum=b1.Sum()n;coutx=b1.Getx()t; cout y= b1.Gety()t;cout z=b1.zn;私有派生私有派生對基類初

18、始化對基類初始化因為因為x是基類私有,所以在派生類和類外中不能直接引用是基類私有,所以在派生類和類外中不能直接引用y是基類保護,所以在派生是基類保護,所以在派生類中可以直接引用。而在類類中可以直接引用。而在類外不可直接引用。外不可直接引用。z是基類公有,私有是基類公有,私有派生變?yōu)樗接校耘缮優(yōu)樗接?,所以在派生類中可直接引在派生類中可直接引用,用,而在類外不可。而在類外不可。這些函數(shù)都是基類公有,這些函數(shù)都是基類公有,在類外不可使用。在類外不可使用。A a1(1,2,3); a1.ShowA();20保護派生class ClassName: protected BaseClassName保

19、護派生時,基類中公有成員和保護成員在派生類中均變?yōu)楸Wo的保護派生時,基類中公有成員和保護成員在派生類中均變?yōu)楸Wo的和私有的,在派生類中仍可直接使用這些成員,和私有的,在派生類中仍可直接使用這些成員,基類中的私有成員,基類中的私有成員,在派生類中不可直接使用。在派生類中不可直接使用。保護派生,派生類中基類公有和保護成員降級使用保護派生,派生類中基類公有和保護成員降級使用基類成員屬性基類成員屬性派生類派生類派生類外派生類外公有公有可以引用可以引用不可引用不可引用保護保護可以引用可以引用不可引用不可引用私有私有不可引用不可引用不可引用不可引用基類:基類:public: (變?yōu)楸Wo變?yōu)楸Wo)在派生類中

20、使用,類外不可使用在派生類中使用,類外不可使用protected: (變?yōu)樗接校┰谂缮愔惺褂?,類外不可使用變?yōu)樗接校┰谂缮愔惺褂?,類外不可使用private: 不能在派生類中和類外使用不能在派生類中和類外使用21x(私有私有)y(保護保護)z(公有公有)A( )Getx()Gety()ShowA()Ax(私私有私私有)y(私有私有)z(保護保護)A( )Getx()Gety()ShowA()Bm(私有私有)n(私有私有)B()Show()Sum()protectedx在類在類B新增加的成員新增加的成員中不能直接調(diào)用中不能直接調(diào)用y在類在類B中可以調(diào)用中可以調(diào)用z在類在類B中可以調(diào)用中可以調(diào)

21、用對類對類B的對象初始化即是對的對象初始化即是對x,y,z,m,n等全部成員的初始化等全部成員的初始化均為保護均為保護類類B 外不外不能引用能引用22protected 成員是一種具有血緣關系內(nèi)外成員是一種具有血緣關系內(nèi)外有別的成員。它對派生類的對象而言,有別的成員。它對派生類的對象而言,是公開成員,可以訪問,對是公開成員,可以訪問,對血緣外部而血緣外部而言,與私有成員一樣被隱蔽言,與私有成員一樣被隱蔽。23抽象類與保護的成員函數(shù)抽象類與保護的成員函數(shù)當定義了一個類,當定義了一個類,這個類這個類只能用作基類只能用作基類來派來派生出新的類,而不能用這種類來定義對象時,生出新的類,而不能用這種類來

22、定義對象時,稱這種類為抽象類。稱這種類為抽象類。當對某些特殊的對象要當對某些特殊的對象要進行很好地封裝時,需要定義抽象類。進行很好地封裝時,需要定義抽象類。將類的構造函數(shù)或析構函數(shù)的訪問權限將類的構造函數(shù)或析構函數(shù)的訪問權限定義為定義為保護保護的時,這種類為的時,這種類為抽象類抽象類。 24當把類中的構造函數(shù)或析構函數(shù)說明為當把類中的構造函數(shù)或析構函數(shù)說明為私有私有的時,所定義的類通常是沒有任何的時,所定義的類通常是沒有任何實用意義的,一般情況下,不能用它來實用意義的,一般情況下,不能用它來產(chǎn)生對象,也不能用它來產(chǎn)生派生類。產(chǎn)生對象,也不能用它來產(chǎn)生派生類。 25x(私有私有)y(私有私有)A

23、( )(保護保護)ShowA()(公有公有)Ax(私私有私私有)y(私私有私私有)A( )(保護保護)ShowA()Bm(私有私有)B()Show()public在類在類B中不能定義中不能定義A的對象的對象在任何時候都不能定義在任何時候都不能定義A的對象的對象但可以在初始化類但可以在初始化類B的對象時初始化的對象時初始化原類原類A中的成員中的成員,因為因為A()在類在類B中是可以被調(diào)用的。中是可以被調(diào)用的。26class A int x, y;protected: A(int a,int b)x=a;y=b;/基類初始化基類初始化public:void ShowA()cout x=xty=yn

24、;class B: public Aint m;A a1; /在派生類中也不可以定義在派生類中也不可以定義A的對象,實際上還是類外調(diào)用的對象,實際上還是類外調(diào)用public: B(int a,int b,int c):A(a,b)/可以在派生類中調(diào)用可以在派生類中調(diào)用A的構造函數(shù)的構造函數(shù) m=c; void Show() cout“m=mn; ShowA(); ;void main(void) B b1(1,2,3); /可以定義派生類對象可以定義派生類對象 b1.Show(); A aa;/不可定義不可定義A的對象的對象 a1(4,5)27多重繼承多重繼承可以用多個基類來派生一個類??梢杂?/p>

25、多個基類來派生一個類。ABCD多重繼承是單多重繼承是單一繼承的擴展一繼承的擴展派生類中新定派生類中新定義的成員義的成員28格式為:格式為:class 類名類名:類名類名1,., 類名類名n private: . ; /私有成員說明私有成員說明; public: . ; /公有成員說明公有成員說明; protected: . ; /保護的成員說明保護的成員說明;繼承方式繼承方式class D: public A, protected B, private C ./派生類中新增加成員派生類中新增加成員;29class A int x1,y1;public: A(int a,int b) x1=a;

26、 y1=b;void ShowA(void) coutA.x=x1tA.y=y1endl; ;class Bint x2,y2;public: B(int a,int b)x2=a; y2=b; void ShowB(void) coutB.x=x2tB.y=y2endl; ;class C:public A,private Bint x,y;public: C(int a,int b,int c,int d,int e,int f):A(a,b),B(c,d)x=e; y=f; void ShowC(void)coutC.x=xtC.y=yendl;ShowA();ShowB();void

27、main(void)C c(1,2,3,4,5,6);c.ShowC();c.ShowA ();c.ShowB ();公有派生公有派生私有派生私有派生仍為公有仍為公有成為私有成為私有非法,私有類外不可調(diào)用非法,私有類外不可調(diào)用B b1(10,20);b1.ShowB();30初始化基類成員初始化基類成員構造函數(shù)不能被繼承構造函數(shù)不能被繼承,派生類的構造函數(shù)派生類的構造函數(shù)必須調(diào)用基類的構造函數(shù)必須調(diào)用基類的構造函數(shù)來初始化基類來初始化基類成員基類成員基類子對象子對象。派生類構造函數(shù)的調(diào)用順序如下:派生類構造函數(shù)的調(diào)用順序如下:基類的構造函數(shù)基類的構造函數(shù)子對象類的構造函數(shù)子對象類的構造函數(shù)派生

28、類的構造函數(shù)派生類的構造函數(shù)31class B:public A int y; A a1;public: B(int a, int b):A(a),a1(3)y=b; .;當撤銷派生類對象時,析當撤銷派生類對象時,析構函數(shù)的調(diào)用正好相反。構函數(shù)的調(diào)用正好相反?;惖臉嬙旌瘮?shù)基類的構造函數(shù)子對象類的構造函數(shù)子對象類的構造函數(shù)派生類的構造函數(shù)派生類的構造函數(shù)32class Base1 int x;public: Base1(int a)x=a;cout調(diào)用基類調(diào)用基類1的構造函數(shù)的構造函數(shù)!n;Base1( )cout調(diào)用基類調(diào)用基類1的析構函數(shù)的析構函數(shù)!n;class Base2 int y;

29、public: Base2(int a) y=a;cout調(diào)用基類調(diào)用基類2的構造函數(shù)的構造函數(shù)!n;Base2( )cout調(diào)用基類調(diào)用基類2的析構函數(shù)的析構函數(shù)!n;class Derived:public Base2, public Base1int z;public: Derived(int a,int b):Base1(a),Base2(20) z=b; cout調(diào)用派生類的構造函數(shù)調(diào)用派生類的構造函數(shù)!n;Derived( )cout調(diào)用派生類的析構函數(shù)調(diào)用派生類的析構函數(shù)!n;void main(void)Derived c(100,200);調(diào)用基類調(diào)用基類2的構造函數(shù)的構造函

30、數(shù)調(diào)用基類調(diào)用基類1的構造函數(shù)的構造函數(shù)調(diào)用派生類的構造函數(shù)調(diào)用派生類的構造函數(shù)調(diào)用派生類的析構函數(shù)調(diào)用派生類的析構函數(shù)調(diào)用基類調(diào)用基類1的析構函數(shù)的析構函數(shù)調(diào)用基類調(diào)用基類2的析構函數(shù)的析構函數(shù)先說明基類先說明基類233class Derived:public Base2, public Base1int z; Base1 b1,b2; public: Derived(int a,int b):Base1(a),Base2(20), b1(200),b2(a+b) z=b; cout調(diào)用派生類的構造函數(shù)調(diào)用派生類的構造函數(shù)!n; Derived( )cout調(diào)用派生類的析構函數(shù)調(diào)用派生類的析

31、構函數(shù)!n;void main(void)Derived c(100,200);基類子對象基類子對象基類成員構造基類成員構造基類子對象構造基類子對象構造基類成員構造用基類名,基類成員構造用基類名,基類子對象構造用對象名基類子對象構造用對象名34class Base1 int x;public: Base1(int a)x=a;cout調(diào)用基類調(diào)用基類1的構造函數(shù)的構造函數(shù)!n;Base1( )cout調(diào)用基類調(diào)用基類1的析構函數(shù)的析構函數(shù)!n;class Base2 int y;public: Base2(int a) y=a;cout調(diào)用基類調(diào)用基類2的構造函數(shù)的構造函數(shù)!n;Base2(

32、)cout調(diào)用基類調(diào)用基類2的析構函數(shù)的析構函數(shù)!n;class Derived:public Base2, public Base1int z; Base1 b1,b2; public: Derived(int a,int b):Base1(a),Base2(20), b1(200),b2(a+b) z=b; cout調(diào)用派生類的構造函數(shù)調(diào)用派生類的構造函數(shù)!n;Derived( )cout調(diào)用派生類的析構函數(shù)調(diào)用派生類的析構函數(shù)!n;void main(void)Derived c(100,200);35調(diào)用基類調(diào)用基類2的構造函數(shù)的構造函數(shù)調(diào)用基類調(diào)用基類1的構造函數(shù)的構造函數(shù)調(diào)用派生類

33、的構造函數(shù)調(diào)用派生類的構造函數(shù)調(diào)用派生類的析構函數(shù)調(diào)用派生類的析構函數(shù)調(diào)用基類調(diào)用基類1的析構函數(shù)的析構函數(shù)調(diào)用基類調(diào)用基類2的析構函數(shù)的析構函數(shù)調(diào)用基類調(diào)用基類1的構造函數(shù)的構造函數(shù)調(diào)用基類調(diào)用基類1的構造函數(shù)的構造函數(shù)調(diào)用基類調(diào)用基類1的析構函數(shù)的析構函數(shù)調(diào)用基類調(diào)用基類1的析構函數(shù)的析構函數(shù)說明基類說明基類1的對象的對象b1,b236class Base1 int x;public: Base1(int a);Base1( );class Base2 int y;public: Base2(int a);Base2( );class Derived:public Base2, publi

34、c Base1int z; Base1 b1,b2; public: Derived(int a,int b);Derived( );xBase1()Base1()Base1yBase2()Base2()Base2DerivedxBase1()Base1()yBase2()Base2()xBase1()Base1()b1xBase1()Base1()b2zDerived()Derived37沖突沖突ABCxA()xB()xC()DA()xB()xC()xD()dD v;v.x=5;public派生類對象派生類對象產(chǎn)生了沖突產(chǎn)生了沖突A:v.x=5;用類作用符限定用類作用符限定38class A

35、public: int x; void Show()cout x=xn; A(int a=0)x=a;class Bpublic: int x; void Show()cout x=xn; B(int a=0)x=a;class C:public A,public Bint y;public: void Setx(int a) x=a; /c1對象中有兩個對象中有兩個x成員成員 void Sety(int b)y=b; int Gety() return y;void main(void)C c1; c1.Show(); /c1對象中有兩個對象中有兩個Show()函數(shù)函數(shù) 這時,可以利用這時,

36、可以利用類作用類作用域符域符:來指明數(shù)據(jù)或函來指明數(shù)據(jù)或函數(shù)的來源。數(shù)的來源。如:如:A:x=a; c1.B:Show();39支配規(guī)則支配規(guī)則AxA()DpublicxA()xD()基類成員基類成員派生類新增成員派生類新增成員D v;v.x=5;當派生類中新增加的數(shù)據(jù)或當派生類中新增加的數(shù)據(jù)或函數(shù)與基類中原有的同名時,函數(shù)與基類中原有的同名時,若不加限制,則若不加限制,則優(yōu)先調(diào)用派優(yōu)先調(diào)用派生類中的成員生類中的成員。540class Apublic: int x;void Show()cout x=xn;class Bpublic: int y;void Show()cout y=yn;cl

37、ass C:public A,public Bpublic: int y; /類類B和類和類C均有均有y的成員的成員;void main(void) C c1; c1.x=100; c1.y=200;/給派生類中的給派生類中的y賦值賦值 c1.B:y=300; /給基類給基類B中的中的y賦值賦值 c1.A:Show(); c1.B:Show(); /用作用域運算符限定調(diào)用的函數(shù)用作用域運算符限定調(diào)用的函數(shù) cout y=c1.yn;/輸出派生類中的輸出派生類中的y值值 cout y=c1.B:yn;/輸出基類輸出基類B中的中的y值值當派生類中新增加的當派生類中新增加的數(shù)據(jù)或函數(shù)與基類中數(shù)據(jù)或函

38、數(shù)與基類中原有的同名時,若不原有的同名時,若不加限制,則加限制,則優(yōu)先調(diào)用優(yōu)先調(diào)用派生類中的成員派生類中的成員。41class Apublic: int x;A(int a=0) x=a;class Bpublic: int y;B(int a=0) y=a;class C:public Aint z;B b1; A a1;public: C(int a,int b,int m):A(a),b1(b),a1(a+b) z=m; void Show( )coutx=xt;couty=b1.yt;coutx=zn;couta1.x=a1.xendl; ;void main(void)C c1(10

39、0,200,500);c1.Show();xzShow()a1.xb1.yC的對象所占空間的對象所占空間從基類從基類A中繼承中繼承在類在類C中新說明中新說明在類在類C中新說明中新說明在類在類C中新說明中新說明在類在類C中新說明中新說明從基類從基類A中繼承中繼承新說明類新說明類A對象中的對象中的x42基類與對象成員基類與對象成員任一基類在派生類中只能繼承一次,否則,會造任一基類在派生類中只能繼承一次,否則,會造成成員名的沖突成成員名的沖突 若在派生類中,確實要有二個以上基類的成員,若在派生類中,確實要有二個以上基類的成員,則可用基則可用基類的二個對象作為派生類的成員。類的二個對象作為派生類的成員

40、。把一個類作為派生類的基類或把一個類的對象作為一個類把一個類作為派生類的基類或把一個類的對象作為一個類的成員,在使用上是有區(qū)別的:在派生類中可直接使用基的成員,在使用上是有區(qū)別的:在派生類中可直接使用基類的成員(訪問權限允許的話),但要類的成員(訪問權限允許的話),但要使用對象成員的使用對象成員的成員時,必須在對象名后加上成員運算符成員時,必須在對象名后加上成員運算符“.”和成和成員名員名。43在平面上作兩個點,連一直線,求直線的長度和在平面上作兩個點,連一直線,求直線的長度和直線中點的坐標。直線中點的坐標?;悶榛悶镈ot,有兩個公有數(shù)據(jù)成員,即平面上的坐,有兩個公有數(shù)據(jù)成員,即平面上的坐

41、標(標(x,y),同時有構造函數(shù)及打印函數(shù)。,同時有構造函數(shù)及打印函數(shù)。派生類為派生類為Line,有,有兩個基類兩個基類Dot對象對象,分別存放兩,分別存放兩點的坐標,同時,從點的坐標,同時,從基類繼承了一個基類繼承了一個Dot數(shù)據(jù)數(shù)據(jù),存,存放直線中點的坐標。放直線中點的坐標。44xyDot(x,y)(構造構造)Dot(&dot)(拷貝拷貝)Show()Dot的對象空間的對象空間x(中點中點)y(中點中點)Dot(x,y)Dot(&dot)Show()d1xyDot(x.y)Dot(&dot)Show()d2xyDot(x,y)Dot(&dot)Show()L

42、ine(dot1,dot2)Showl()Line對象對象空間空間從基類從基類繼承繼承基類基類對象對象45class Dotpublic: float x,y;Dot(float a=0,float b=0) x=a; y=b;void Show(void)coutx=xty=yendl;class Line:public DotDot d1,d2;public: Line(Dot dot1,Dot dot2):d1(dot1),d2(dot2) x=(d1.x+d2.x)/2; y=(d1.x+d2.y)/2; void Showl(void) coutDot1: ; d1.Show();

43、coutDot2: ; d2.Show(); coutLength=sqrt(d1.x-d2.x)*(d1.x-d2.x)+(d1.y-d2.y)*(d1.y-d2.y)endl; coutCenter: x=xty=yendl;void main(void) float a,b; coutab; Dot dot1(a,b);/調(diào)用調(diào)用Dot的構造函數(shù)的構造函數(shù) coutab; Dot dot2(a,b); Line line(dot1,dot2); line.Showl();用坐標初始化用坐標初始化Dot對象對象在在Line中新說明的成員中新說明的成員對成員初始化對成員初始化x,y是繼承基類

44、的成員是繼承基類的成員打印坐標打印坐標46 賦值兼容規(guī)則賦值兼容規(guī)則基類基類對象對象派生類派生類對象對象 相互之間能否賦值?相互之間能否賦值? 可以將派生類對象的值賦給基類對象??梢詫⑴缮悓ο蟮闹蒂x給基類對象。反之不行反之不行Base b;Derive d; b = d; 只是將從基類只是將從基類繼承來的成員繼承來的成員賦值。賦值。47Show()Dot(&dot)Dot(x,y)yxDot的對象空間的對象空間Show()Dot(&dot)Dot(x,y)Show()Dot(&dot)Dot(x,y)yDot(&dot)Show()Dot(x.y)yxxSho

45、wl()Line()d2d1yxLine的對的對象空間象空間從基類從基類繼承繼承基類基類對象對象Dot dot;Line line;dot=line;line=dot;非法非法48可以將一個派生類對象的地址賦給基類的指針變可以將一個派生類對象的地址賦給基類的指針變量。量?;悓ο蠡悓ο笈缮悓ο笈缮悓ο驜ase b;Derive d;Base *basep;basepbasep=&b;basepbasep = &dbasep只能引用只能引用從基類繼承來從基類繼承來的成員。的成員?;愔羔樆愔羔樑缮悓ο笈缮悓ο蠡悓ο蠡悓ο?9派生類對象可以初始化基類的引用。派生類對

46、象可以初始化基類的引用。Derive d;Base basei=&d;基類對象基類對象派生類對象派生類對象Base b;Derive d;別名別名baseibasei只能引用只能引用從基類繼承來從基類繼承來的成員。的成員?;愐没愐门缮悓ο笈缮悓ο?0class Apublic: int x;A(int a=0) x=a;class Bpublic: int y;B(int a=0) y=a;class C:public A,public B int z;public: C(int a,int b,int m): A(a), B(b) z=m; void Show( )cou

47、tx=xt;couty=yt;coutz=zn;void main(void)A a1(100);B b1(200);C c1(10,20,50);couta1.x=a1.xendl;coutb1.y=b1.yendl;c1.Show();a1=c1; b1=c1;/派生類對象向基類對象賦值派生類對象向基類對象賦值couta1.x=a1.xendl;coutb1.y=b1.yShow();xA( ) yB( )zC( )Show( )102050a1.x=100b1.y=200 x=10y=20z=50a1.x=10b1.y=20c1xA( )a1yB( )b11002001020錯誤!錯誤!

48、51虛基類虛基類 類類B 是類是類A的派生類的派生類xA()xA()yB()xA()zC()A類類B類類C類類dxD()xA()zC()yB()A()xD類類類類A拷貝拷貝類類C 是類是類A的派生類的派生類類類D 是類是類B和類和類C的派生類的派生類這樣,類這樣,類D中就有兩份類中就有兩份類A的拷貝的拷貝B類類C類類類類A拷貝拷貝52這種同一個公共的基類這種同一個公共的基類在派生類中產(chǎn)生多個拷在派生類中產(chǎn)生多個拷貝,不僅多占用了存儲貝,不僅多占用了存儲空間,空間,而且可能會造成而且可能會造成多個拷貝中的數(shù)據(jù)不一多個拷貝中的數(shù)據(jù)不一致致 和模糊的引用和模糊的引用。D d;d.x=10; /模糊引

49、用模糊引用dxD()xA()zC()yB()A()xD類類類類A拷貝拷貝B類類C類類類類A拷貝拷貝53class Apublic: int x;A(int a=0) x=a;class B:public Apublic: int y;B(int a=0,int b=0):A(a) y=b;class C:public Apublic: int z;C(int a,int c):A(a) z=c; ;class D:public B,public Cpublic: int dx;D(int a1,int b,int c,int d,int a2):B(a1,b),C(a2,c)dx=d;void

50、 main(void)D d1(10,20,30,40,50); coutd1.xendl; dxD()xA()zC()yB()A()xD類類a1=10b=20a2=50c=30dx=40模糊引用,錯誤!模糊引用,錯誤!54在多重派生的過程中,若使公共基類在派生類中在多重派生的過程中,若使公共基類在派生類中只有一個拷貝,則可將這種基類說明為只有一個拷貝,則可將這種基類說明為虛基類虛基類。class B:public virtual Apublic:int y;B(int a=0, int b=0 ):A(b) y=a;在派生類的定義中,只要在基類的類名前加上關在派生類的定義中,只要在基類的類名

51、前加上關鍵字鍵字virtual,就可以將基類說明為虛基類,就可以將基類說明為虛基類。55xA()xA()yB()xA()zC()A類類B類類C類類xA()yB()zC()dxD()D類類一份拷貝,在一份拷貝,在D( )的構造函數(shù)中直的構造函數(shù)中直接調(diào)用接調(diào)用A()由虛基類派生出的對象初始由虛基類派生出的對象初始化時,化時,直接調(diào)用直接調(diào)用虛基類的構虛基類的構造函數(shù)。因此,若將一個類造函數(shù)。因此,若將一個類定義為虛基類,定義為虛基類,則一定有正則一定有正確的構造函數(shù)可供所有派生確的構造函數(shù)可供所有派生類調(diào)用。類調(diào)用。56class Apublic: int x;A(int a=0) x=a;cl

52、ass B:public virtual Apublic: int y;B(int a=0,int b=0): A(a) y=b;class C:public virtual Apublic: int z;C(int a=0,int c=0):A(a)z=c; ;class D:public B,public Cpublic: int dx;D(int a1,int b,int c,int d,int a2):B(a1,b),C(a2,c)dx=d;void main(void)D d1(10,20,30,40,50); coutd1.xendl; d1.x=400;coutd1.xendl;

53、coutd1.yendl;040020沒有對虛基類構造函數(shù)的調(diào)用,用缺省的構造函數(shù)沒有對虛基類構造函數(shù)的調(diào)用,用缺省的構造函數(shù), A(a2)直接在派生類中調(diào)用虛基類的構造函數(shù)直接在派生類中調(diào)用虛基類的構造函數(shù)504002057再次強調(diào),用虛基類進行多重派生時,再次強調(diào),用虛基類進行多重派生時,若虛若虛基類沒有缺省的構造函數(shù)基類沒有缺省的構造函數(shù),則在每一個派生,則在每一個派生類的構造函數(shù)中類的構造函數(shù)中都必須有對虛基類構造函數(shù)都必須有對虛基類構造函數(shù)的調(diào)用的調(diào)用 (且首先調(diào)用)。(且首先調(diào)用)。58第十二章第十二章 類的其它特性類的其它特性 59友元函數(shù)友元函數(shù)類中私有和保護的成員在類外不能被

54、訪問。類中私有和保護的成員在類外不能被訪問。友元函數(shù)是一種定義在類外部的友元函數(shù)是一種定義在類外部的普通函普通函數(shù)數(shù),其特點是,其特點是能夠訪問類中私有成員和能夠訪問類中私有成員和保護成員保護成員,即類的訪問權限的限制對其,即類的訪問權限的限制對其不起作用。不起作用。60友元函數(shù)需要在友元函數(shù)需要在類體內(nèi)類體內(nèi)進行說明,在前面加進行說明,在前面加上關鍵字上關鍵字friend。一般格式為:一般格式為:friend FuncName();friend float Volume(A &a);關鍵字關鍵字返回值類型返回值類型函數(shù)名函數(shù)名函數(shù)參數(shù)函數(shù)參數(shù)61友元函數(shù)不是成員函數(shù)友元函數(shù)不是成員函

55、數(shù),用法也與普通,用法也與普通的函數(shù)完全一致,的函數(shù)完全一致,只不過它能訪問類中只不過它能訪問類中所有的數(shù)據(jù)所有的數(shù)據(jù)。友元函數(shù)破壞了類的封裝友元函數(shù)破壞了類的封裝性和隱蔽性,使得非成員函數(shù)可以訪問性和隱蔽性,使得非成員函數(shù)可以訪問類的私有成員類的私有成員。一個類的友元可以自由地用該類中的所有成員。一個類的友元可以自由地用該類中的所有成員。62class Afloat x,y;public: A(float a, float b) x=a; y=b; float Sum() return x+y; friend float Sum(A &a) return a.x+a.y; ;void

56、 main(void) A t1(4,5),t2(10,20); coutt1.Sum()endl; coutSum(t2)endl;友元函數(shù)友元函數(shù)成員函數(shù)成員函數(shù)友元函數(shù)的調(diào)用,直接調(diào)用友元函數(shù)的調(diào)用,直接調(diào)用成員函數(shù)的調(diào)用,利用對象名調(diào)用成員函數(shù)的調(diào)用,利用對象名調(diào)用友元函數(shù)只能用友元函數(shù)只能用對象對象名名引用類中的數(shù)據(jù)。引用類中的數(shù)據(jù)。私有數(shù)據(jù)私有數(shù)據(jù)63有關友元函數(shù)的使用,說明如下:有關友元函數(shù)的使用,說明如下:友元函數(shù)不是類的成員函數(shù)友元函數(shù)不是類的成員函數(shù)友元函數(shù)近似于友元函數(shù)近似于普通的函數(shù)普通的函數(shù),它不帶有,它不帶有this指針,指針,因此必須將對象名或對象的引用作為因此必

57、須將對象名或對象的引用作為友元函數(shù)的參數(shù)友元函數(shù)的參數(shù),這樣才能訪問到對象的成,這樣才能訪問到對象的成員。員。64友元函數(shù)與一般函數(shù)的不同點在于友元函數(shù)與一般函數(shù)的不同點在于: 友元函數(shù)必須在類的定義中說明,友元函數(shù)必須在類的定義中說明,其其函數(shù)體可在類內(nèi)定義,也可在類外定函數(shù)體可在類內(nèi)定義,也可在類外定義義;1.它可以訪問該類中的所有成員(公有它可以訪問該類中的所有成員(公有的、私有的和保護的)的、私有的和保護的),而一般函數(shù),而一般函數(shù)只能訪問類中的公有成員。只能訪問類中的公有成員。65class Afloat x,y;public: A(float a, float b) x=a; y=

58、b; float Getx() return x; float Gety() return y; float Sum() return x+y; friend float Sum(A &); ;float Sumxy(A &a) return a.Getx()+a.Gety(); float Sum(A &a) return a.x+a.y; void main(void) A t1(1,2),t2(10,20), t3(100,200); coutt1.Sum()endl; coutSum(t2)endl; coutSumxy(t3)endl;成員函數(shù)成員函數(shù)友元函數(shù)

59、友元函數(shù),可以直接調(diào)用類中私有成員可以直接調(diào)用類中私有成員普通函數(shù),必須通過公有函數(shù)訪問私有成員普通函數(shù),必須通過公有函數(shù)訪問私有成員對象調(diào)用成員函數(shù)對象調(diào)用成員函數(shù)調(diào)用友元函數(shù)調(diào)用友元函數(shù)調(diào)用一般函數(shù)調(diào)用一般函數(shù)友元函數(shù)友元函數(shù)66友元函數(shù)不受類中訪問權限關鍵字的限制,可以友元函數(shù)不受類中訪問權限關鍵字的限制,可以把它放在類的私有部分,放在類的公有部分或放把它放在類的私有部分,放在類的公有部分或放在類的保護部分,其作用都是一樣的。換言之,在類的保護部分,其作用都是一樣的。換言之,在類中對友元函數(shù)指定訪問權限是不起作用的在類中對友元函數(shù)指定訪問權限是不起作用的。友元函數(shù)的作用域與一般函數(shù)的作用

60、域相同。友元函數(shù)的作用域與一般函數(shù)的作用域相同。謹慎使用友元函數(shù)謹慎使用友元函數(shù)通常使用友元函數(shù)來通常使用友元函數(shù)來取取對象中的數(shù)據(jù)成員值,而對象中的數(shù)據(jù)成員值,而不修改不修改對象中的成員值,則肯定是安全的。對象中的成員值,則肯定是安全的。67大多數(shù)情況是友元函數(shù)是某個類的成員函數(shù),大多數(shù)情況是友元函數(shù)是某個類的成員函數(shù),即即A類中的某個成員函數(shù)是類中的某個成員函數(shù)是B類中的友元函數(shù),這個成類中的友元函數(shù),這個成員函數(shù)可以直接訪問員函數(shù)可以直接訪問B類中的私有數(shù)據(jù)。類中的私有數(shù)據(jù)。這就實現(xiàn)這就實現(xiàn)了類與類之間的溝通了類與類之間的溝通。注意:一個類的成員函數(shù)作為另一個類的友元函數(shù)時,注意:一個類的成員函數(shù)作為另一個類的友元函數(shù)時,應應先定義友元函數(shù)所在的類。先定義友元函數(shù)所在的類。class A.void fun( B &);class B.friend void

溫馨提示

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

評論

0/150

提交評論