c++類的重用與多態(tài)性.ppt_第1頁(yè)
c++類的重用與多態(tài)性.ppt_第2頁(yè)
c++類的重用與多態(tài)性.ppt_第3頁(yè)
c++類的重用與多態(tài)性.ppt_第4頁(yè)
c++類的重用與多態(tài)性.ppt_第5頁(yè)
已閱讀5頁(yè),還剩78頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、目錄,10.1 類的組合 10.2 類的繼承與派生 10.3 訪問控制 10.4 類型兼容規(guī)則 10.5 多態(tài)性 10.6 派生類的構(gòu)造、析構(gòu)函數(shù) 10.7 派生類成員的標(biāo)識(shí)與訪問 10.8 小結(jié),1,10.1.1組合,類中的成員數(shù)據(jù)是另一個(gè)類的對(duì)象。 可以在已有抽象的基礎(chǔ)上實(shí)現(xiàn)更復(fù)雜的抽象。,2,10.1 類的組合,類組合的構(gòu)造函數(shù)設(shè)計(jì),原則:不僅要負(fù)責(zé)對(duì)本類中的基本類型成員數(shù)據(jù)賦初值,也要對(duì)對(duì)象成員初始化。 聲明形式: 類名:類名(對(duì)象成員所需的形參,本類成員形參) :對(duì)象1(參數(shù)),對(duì)象2(參數(shù)),. 本類初始化 ,3,10.1 類的組合 10.1.1 組合,類組合的構(gòu)造函數(shù)調(diào)用,構(gòu)造函

2、數(shù)調(diào)用順序:先調(diào)用內(nèi)嵌對(duì)象的構(gòu)造函數(shù)(按內(nèi)嵌時(shí)的聲明順序,先聲明者先構(gòu)造)。然后調(diào)用本類的構(gòu)造函數(shù)。(析構(gòu)函數(shù)的調(diào)用順序相反) 初始化列表中未出現(xiàn)的內(nèi)嵌對(duì)象,用默認(rèn)構(gòu)造函數(shù)(即無形參的)初始化 系統(tǒng)自動(dòng)生成的隱含的默認(rèn)構(gòu)造函數(shù)中,內(nèi)嵌對(duì)象全部用默認(rèn)構(gòu)造函數(shù)初始化,4,10.1 類的組合 10.1.1 組合,例10-1(教材例4-4)類的組合,線段(Line)類,/4_4.cpp #include #include using namespace std; class Point /Point類定義 public: Point(int xx = 0, int yy = 0) x = xx; y

3、= yy; Point(Point ,5,10.1 類的組合 10.1.1 組合,/類的組合 class Line /Line類的定義 public:/外部接口 Line(Point xp1, Point xp2); Line(Line ,6,10.1 類的組合 10.1.1 組合,例10-1(續(xù)),/主函數(shù) int main() Point myp1(1, 1), myp2(4, 5);/建立Point類的對(duì)象 Line line(myp1, myp2);/建立Line類的對(duì)象 Line line2(line);/利用拷貝構(gòu)造函數(shù)建立一個(gè)新對(duì)象 cout The length of the

4、line is: ; cout line.getLen() endl; cout The length of the line2 is: ; cout line2.getLen() endl; return 0; ,7,10.1 類的組合 10.1.1 組合,例10-1(續(xù)),運(yùn)行結(jié)果如下: Calling the copy constructor of Point Calling the copy constructor of Point Calling the copy constructor of Point Calling the copy constructor of Point C

5、alling constructor of Line Calling the copy constructor of Point Calling the copy constructor of Point Calling the copy constructor of Line The length of the line is: 5 The length of the line2 is: 5,10.1.2 前向引用聲明,類應(yīng)該先聲明,后使用 如果需要在某個(gè)類的聲明之前,引用該類,則應(yīng)進(jìn)行前向引用聲明。 前向引用聲明只為程序引入一個(gè)標(biāo)識(shí)符,但具體聲明在其他地方。,8,10.1 類的組合,舉例,

6、class B; /前向引用聲明 class A public: void f(B b); ; class B public: void g(A a); ;,9,10.1 類的組合 10.1.2 前向引用聲明,前向引用聲明注意事項(xiàng),使用前向引用聲明雖然可以解決一些問題,但它并不是萬能的。需要注意的是,盡管使用了前向引用聲明,但是在提供一個(gè)完整的類聲明之前,不能聲明該類的對(duì)象,也不能在內(nèi)聯(lián)成員函數(shù)中使用該類的對(duì)象。請(qǐng)看下面的程序段:,10,10.1 類的組合 10.1.2 前向引用聲明,class Fred; /前向引用聲明 class Barney Fred x; /錯(cuò)誤:類Fred的聲明尚不

7、完善 ; class Fred Barney y; ;,正確的程序,11,class Fred;/前向引用聲明 class Barney Fred *x; ; class Fred Barney y; ;,10.1 類的組合 10.1.2 前向引用聲明,class Fred;/前向引用聲明 class Barney public: void method() x.yabbaDabbaDo();/錯(cuò)誤:Fred類的對(duì)象在定義之前被使用 private: Fred ,前向引用聲明注意事項(xiàng)(續(xù)),12,10.1 類的組合 10.1.2 前向引用聲明,前向引用聲明注意事項(xiàng)(續(xù)),應(yīng)該記?。寒?dāng)你使用前向

8、引用聲明時(shí),你只能使用被聲明的符號(hào),而不能涉及類的任何細(xì)節(jié)。,13,10.1 類的組合 10.1.2 前向引用聲明,10.2 類的繼承與派生,保持已有類的特性而構(gòu)造新類的過程稱為繼承。 在已有類的基礎(chǔ)上新增自己的特性而產(chǎn)生新類的過程稱為派生。 被繼承的已有類稱為基類(或父類)。 派生出的新類稱為派生類。,14,10.2 類的繼承與派生,繼承與派生的目的,繼承的目的:實(shí)現(xiàn)代碼重用。 派生的目的:當(dāng)新的問題出現(xiàn),原有程序無法解決(或不能完全解決)時(shí),需要對(duì)原有程序進(jìn)行改造。,15,10.2 類的繼承與派生 10.2.1 派生與繼承的實(shí)例,10.2.2派生類的聲明,class 派生類名:繼承方式 基

9、類名 成員聲明; 例如: class Derived: public Base1, private Base2 public: Derived (); Derived (); ;,16,10.2 類的繼承與派生 10.2.2 派生類的定義,繼承方式,一個(gè)派生類,可以同時(shí)有多個(gè)基類,這種情況稱為多繼承 一個(gè)派生類只有一個(gè)直接基類的情況,稱為單繼承。 直接參與派生出某類的基類稱為直接基類,基類的基類甚至更高層的基類稱為間接基類。 派生類成員是指除了從基類繼承來的所有成員之外,新增加的數(shù)據(jù)和函數(shù)成員。,17,10.2 類的繼承與派生 10.2.2 派生類的定義,10.2.3 派生類生成過程,派生新類

10、經(jīng)歷了三個(gè)步驟: 吸收基類成員 吸收基類成員之后,派生類實(shí)際上就包含了它的全部基類中除構(gòu)造和析構(gòu)函數(shù)之外的所有成員。 改造基類成員 如果派生類聲明了一個(gè)和某基類成員同名的新成員(如果是成員函數(shù),則參數(shù)表也要相同,參數(shù)不同的情況屬于重載),派生的新成員就覆蓋了外層同名成員 添加新的成員 派生類新成員的加入是繼承與派生機(jī)制的核心,是保證派生類在功能上有所發(fā)展,18,10.2 類的繼承與派生,10.3 訪問控制,不同繼承方式的影響主要體現(xiàn)在: 派生類成員對(duì)基類成員的訪問權(quán)限 通過派生類對(duì)象對(duì)基類成員的訪問權(quán)限 三種繼承方式 公有繼承 私有繼承 保護(hù)繼承,19,10.3 訪問控制,10.3.1 公有繼

11、承(public),基類的public和protected成員的訪問屬性在派生類中保持不變,但基類的private成員不可直接訪問。 派生類中的成員函數(shù)可以直接訪問基類中的public和protected成員,但不能直接訪問基類的private成員。 通過派生類的對(duì)象只能訪問基類的public成員。,20,10.3 訪問控制 10.3.1 公有繼承,21,例10-2(教材例7-1) 公有繼承舉例,/Point.h #ifndef _POINT_H #define _POINT_H class Point /基類Point類的定義 public:/公有函數(shù)成員 void initPoint(fl

12、oat x = 0, float y = 0) this-x = x; this-y = y; void move(float offX, float offY) x += offX; y += offY; float getX() const return x; float getY() const return y; private:/私有數(shù)據(jù)成員 float x, y; ; #endif /_POINT_H,10.3 訪問控制 10.3.1 公有繼承,22,例10-2 (續(xù)),/Rectangle.h #ifndef _RECTANGLE_H #define _RECTANGLE_H #

13、include Point.h class Rectangle: public Point /派生類定義部分 public:/新增公有函數(shù)成員 void initRectangle(float x, float y, float w, float h) initPoint(x, y); /調(diào)用基類公有成員函數(shù) this-w = w; this-h = h; float getH() const return h; float getW() const return w; private:/新增私有數(shù)據(jù)成員 float w, h; ; #endif /_RECTANGLE_H,10.3 訪問控制

14、 10.3.1 公有繼承,23,例10-2 (續(xù)),#include #include using namespace std; int main() Rectangle rect;/定義Rectangle類的對(duì)象 /設(shè)置矩形的數(shù)據(jù) rect.initRectangle(2, 3, 20, 10); rect.move(3,2);/移動(dòng)矩形位置 cout The data of rect(x,y,w,h): endl; /輸出矩形的特征參數(shù) cout rect.getX() , rect.getY() , rect.getW() , rect.getH() endl; return 0; ,1

15、0.3 訪問控制 10.3.1 公有繼承,10.3.2 私有繼承(private),基類的public和protected成員都以private身份出現(xiàn)在派生類中,但基類的private成員不可直接訪問。 派生類中的成員函數(shù)可以直接訪問基類中的public和protected成員,但不能直接訪問基類的private成員。 通過派生類的對(duì)象不能直接訪問基類中的任何成員。,24,10.3 訪問控制 10.3.2 私有繼承,25,例10-3(教材例7-2) 私有繼承舉例,/Point.h #ifndef _POINT_H #define _POINT_H class Point /基類Point類的

16、定義 public:/公有函數(shù)成員 void initPoint(float x = 0, float y = 0) this-x = x; this-y = y; void move(float offX, float offY) x += offX; y += offY; float getX() const return x; float getY() const return y; private:/私有數(shù)據(jù)成員 float x, y; ; #endif /_POINT_H,10.3 訪問控制 10.3.2 私有繼承,26,例10-3 (續(xù)),/Rectangle.h #ifndef

17、_RECTANGLE_H #define _RECTANGLE_H #include Point.h class Rectangle: private Point /派生類定義部分 public:/新增公有函數(shù)成員 void initRectangle(float x, float y, float w, float h) initPoint(x, y); /調(diào)用基類公有成員函數(shù) this-w = w; this-h = h; void move(float offX, float offY) Point:move(offX, offY); float getX() const return

18、Point:getX(); float getY() const return Point:getY(); float getH() const return h; float getW() const return w; private:/新增私有數(shù)據(jù)成員 float w, h; ; #endif /_RECTANGLE_H,10.3 訪問控制 10.3.2 私有繼承,27,例10-3 (續(xù)),#include #include using namespace std; int main() Rectangle rect;/定義Rectangle類的對(duì)象 rect.initRectangle

19、(2, 3, 20, 10);/設(shè)置矩形的數(shù)據(jù) rect.move(3,2);/移動(dòng)矩形位置 cout The data of rect(x,y,w,h): endl; cout rect.getX() , /輸出矩形的特征參數(shù) rect.getY() , rect.getW() , rect.getH() endl; return 0; ,10.3 訪問控制 10.3.2 私有繼承,10.3.3 保護(hù)繼承(protected),基類的public和protected成員都以protected身份出現(xiàn)在派生類中,但基類的private成員不可直接訪問。 派生類中的成員函數(shù)可以直接訪問基類中的p

20、ublic和protected成員,但不能直接訪問基類的private成員。 通過派生類的對(duì)象不能直接訪問基類中的任何成員,28,10.3 訪問控制 10.3.3 保護(hù)繼承,protected 成員的特點(diǎn)與作用,對(duì)建立其所在類對(duì)象的模塊來說,它與 private 成員的性質(zhì)相同。 對(duì)于其派生類來說,它與 public 成員的性質(zhì)相同。 既實(shí)現(xiàn)了數(shù)據(jù)隱藏,又方便繼承,實(shí)現(xiàn)代碼重用。,29,10.3 訪問控制 10.3.3 保護(hù)繼承,30,例: protected 成員舉例,class A protected: int x; ; int main() A a; a.x = 5; /錯(cuò)誤 ,10.3

21、 訪問控制 10.3.3 保護(hù)繼承,31,例 (續(xù)),class A protected: int x; ; class B: public A public: void function(); ; void B:function() x = 5; /正確 ,10.3 訪問控制 10.3.3 保護(hù)繼承,10.4 類型兼容規(guī)則,一個(gè)公有派生類的對(duì)象在使用上可以被當(dāng)作基類的對(duì)象,反之則禁止。具體表現(xiàn)在: 派生類的對(duì)象可以隱含轉(zhuǎn)換為基類對(duì)象。 派生類的對(duì)象可以初始化基類的引用。 派生類的指針可以隱含轉(zhuǎn)換為基類的指針。 通過基類對(duì)象名、指針只能使用從基類繼承的成員,32,10.4 類型兼容規(guī)則,33,

22、例10-4(教材例7-3)類型兼容規(guī)則舉例,#include using namespace std; class Base1 /基類Base1定義 public: void display() const cout Base1:display() endl; ; class Base2: public Base1 /公有派生類Base2定義 public: void display() const cout Base2:display() endl; ; class Derived: public Base2 /公有派生類Derived定義 public: void display() co

23、nst cout Derived:display() endl; ;,10.4 類型兼容規(guī)則,34,例10-4 (續(xù)),void fun(Base1 *ptr) /參數(shù)為指向基類對(duì)象的指針 ptr-display();/對(duì)象指針-成員名 int main() /主函數(shù) Base1 base1;/聲明Base1類對(duì)象 Base2 base2;/聲明Base2類對(duì)象 Derived derived;/聲明Derived類對(duì)象 fun( ,10.4 類型兼容規(guī)則,運(yùn)行結(jié)果: Base1:display() Base1:display() Base1:display(),絕對(duì)不要重新定義繼承而來的非虛

24、函數(shù),10.5.1 一般虛函數(shù)成員,C+中引入了虛函數(shù)的機(jī)制在派生類中可以對(duì)基類中的成員函數(shù)進(jìn)行覆蓋(重定義)。 虛函數(shù)的聲明 Virtual 函數(shù)類型 函數(shù)名(形參表) 函數(shù)體 ,35,10.5 多態(tài)性,例10-5(教材例8-4)虛函數(shù)成員,#include using namespace std; class Base1 /基類Base1定義 public: virtual void display() const;/虛函數(shù) ; void Base1:display() const cout Base1:display() endl; class Base2:public Base1 /公

25、有派生類Base2定義 public: void display() const;/覆蓋基類的虛函數(shù) ; void Base2:display() const cout Base2:display() endl; ,36,10.5 多態(tài)性 10.5.1 一般虛函數(shù)成員,class Derived: public Base2 /公有派生類 public: void display() const; /覆蓋基類的虛函數(shù) ; void Derived:display() const cout display();/對(duì)象指針-成員名 int main() /主函數(shù) Base1 base1;/定義Bas

26、e1類對(duì)象 Base2 base2;/定義Base2類對(duì)象 Derived derived;/定義Derived類對(duì)象 fun( ,37,例10-5(續(xù)),10.5 多態(tài)性 10.5.1 一般虛函數(shù)成員,運(yùn)行結(jié)果: Base1:display() Base2:display() Derived:display(),10.5.2 虛析構(gòu)函數(shù),為什么需要虛析構(gòu)函數(shù)? 可能通過基類指針刪除派生類對(duì)象; 如果你打算允許其他人通過基類指針調(diào)用對(duì)象的析構(gòu)函數(shù)(通過delete這樣做是正常的),就需要讓基類的析構(gòu)函數(shù)成為虛函數(shù),否則執(zhí)行delete的結(jié)果是不確定的。,38,10.5 多態(tài)性,例10-6(教材

27、例8-5)虛析構(gòu)函數(shù)舉例,#include using namespace std; class Base public: Base(); ; Base:Base() cout Base destructor endl; class Derived: public Base public: Derived(); Derived();,39,10.5 多態(tài)性 10.5.2 虛析構(gòu)函數(shù),private: int *p; ; Derived:Derived() p = new int(0); Derived:Derived() cout Derived destructor endl; delete

28、 p; void fun(Base* b) delete b; int main() Base *b = new Derived(); fun(b); return 0; ,例10-6(續(xù)),運(yùn)行時(shí)結(jié)果: Base destructor 避免上述錯(cuò)誤的有效方法就是將析構(gòu)函數(shù)聲明為虛函數(shù),運(yùn)行結(jié)果變?yōu)椋?Derived destructor Base destructor,40,10.5 多態(tài)性 10.5.2 虛析構(gòu)函數(shù),41,class Base public: virtual void f(); virtual void g(); private: int i; ;,class Derive

29、d: public Base public: virtual void f(); /覆蓋Base:f virtual void h(); /新增的虛函數(shù) private: int j; ;,10.5 多態(tài)性 10.5.3虛函數(shù)動(dòng)態(tài)綁定的實(shí)現(xiàn)原理,10.5.4 純虛函數(shù),純虛函數(shù)是一個(gè)在基類中聲明的虛函數(shù),它在該基類中沒有定義具體的操作內(nèi)容,要求各派生類根據(jù)實(shí)際需要定義自己的版本,純虛函數(shù)的聲明格式為: virtual 函數(shù)類型 函數(shù)名(參數(shù)表) = 0; 帶有純虛函數(shù)的類稱為抽象類: class 類名 virtual 類型 函數(shù)名(參數(shù)表)=0; /純虛函數(shù) . ,42,10.5 多態(tài)性,10

30、.5.5 抽象類,作用 抽象類為抽象和設(shè)計(jì)的目的而聲明,將有關(guān)的數(shù)據(jù)和行為組織在一個(gè)繼承層次結(jié)構(gòu)中,保證派生類具有要求的行為。 對(duì)于暫時(shí)無法實(shí)現(xiàn)的函數(shù),可以聲明為純虛函數(shù),留給派生類去實(shí)現(xiàn)。 注意 抽象類只能作為基類來使用。 不能聲明抽象類的對(duì)象。 構(gòu)造函數(shù)不能是虛函數(shù),析構(gòu)函數(shù)可以是虛函數(shù)。,43,10.5 多態(tài)性,例10-7(教材例8-6)抽象類舉例,/8_6.cpp #include using namespace std; class Base1 /基類Base1定義 public: virtual void display() const = 0;/純虛函數(shù) ; class Base

31、2: public Base1 /公有派生類Base2定義 public: void display() const;/覆蓋基類的虛函數(shù) ; void Base2:display() const cout Base2:display() endl; ,44,10.5 多態(tài)性 10.5.5 抽象類,class Derived: public Base2 /公有派生類Derived定義 public: void display() const;/覆蓋基類的虛函數(shù) ; void Derived:display() const cout display();/對(duì)象指針-成員名 int main() /

32、主函數(shù) Base2 base2;/定義Base2類對(duì)象 Derived derived;/定義Derived類對(duì)象 fun( ,45,10.5 多態(tài)性 10.5.5 抽象類,例10-7(續(xù)),運(yùn)行結(jié)果: Base2:display() Derived:display(),基類與派生類的對(duì)應(yīng)關(guān)系,單繼承 派生類只從一個(gè)基類派生。 多繼承 派生類從多個(gè)基類派生。 多重派生 由一個(gè)基類派生出多個(gè)不同的派生類。 多層派生 派生類又作為基類,繼續(xù)派生新的類。,46,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),多繼承時(shí)派生類的聲明,class 派生類名:繼承方式1 基類名1,繼承方式2 基類

33、名2,. 成員聲明; 注意:每一個(gè)“繼承方式”,只用于限制對(duì)緊隨其后之基類的繼承。,47,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),例10-8多繼承舉例,class A public: void setA(int); void showA() const; private: int a; ; class B public: void setB(int); void showB() const;,private: int b; ; class C : public A, private B public: void setC(int, int, int); void showC(

34、) const; private const: int c; ;,48,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),例10-8 (續(xù)),void A:setA(int x) a=x; void B:setB(int x) b=x; void C:setC(int x, int y, int z) /派生類成員直接訪問基類的 /公有成員 setA(x); setB(y); c = z; /其他函數(shù)實(shí)現(xiàn)略,int main() C obj; obj.setA(5); obj.showA(); obj.setC(6,7,9); obj.showC(); / obj.setB(6); 錯(cuò)

35、誤 / obj.showB(); 錯(cuò)誤 return 0; ,49,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),繼承時(shí)的構(gòu)造函數(shù),基類的構(gòu)造函數(shù)不被繼承,派生類中需要聲明自己的構(gòu)造函數(shù)。 定義構(gòu)造函數(shù)時(shí),只需要對(duì)本類中新增成員進(jìn)行初始化,對(duì)繼承來的基類成員的初始化,自動(dòng)調(diào)用基類構(gòu)造函數(shù)完成。 派生類的構(gòu)造函數(shù)需要給基類的構(gòu)造函數(shù)傳遞參數(shù),50,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),單一繼承時(shí)的構(gòu)造函數(shù),派生類名:派生類名(基類所需的形參,本類成員所需的形參):基類名(參數(shù)表) 本類成員初始化賦值語(yǔ)句; ;,51,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1

36、構(gòu)造函數(shù),52,例10-9單一繼承時(shí)的構(gòu)造函數(shù)舉例,#include using namecpace std; class B public: B(); B(int i); B(); void print() const; private: int b; ;,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),53,例10-9 (續(xù)),B:B() b=0; cout Bs default constructor called. endl; B:B(int i) b=i; cout Bs constructor called. endl; B:B() cout Bs destructor

37、called. endl; void B:print() const cout b endl; ,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),54,例10-9 (續(xù)),class C: public B public: C(); C(int i, int j); C(); void print() const; private: int c; ; C:C() c = 0; cout Cs default constructor called. endl; C:C(int i,int j): B(i) c = j; cout Cs constructor called. endl;

38、 ,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),55,例10-9 (續(xù)),C:C() cout Cs destructor called. endl; void C:print() const B:print(); cout c endl; int main() C obj(5, 6); obj.print(); return 0; ,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),多繼承時(shí)的構(gòu)造函數(shù),派生類名:派生類名(參數(shù)表):基類名1(基類1初始化參數(shù)表), 基類名2(基類2初始化參數(shù)表), .基類名n(基類n初始化參數(shù)表) 本類成員初始化賦值語(yǔ)句; ;,56,1

39、0.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),派生類與基類的構(gòu)造函數(shù),當(dāng)基類中聲明有缺省構(gòu)造函數(shù)或未聲明構(gòu)造函數(shù)時(shí),派生類構(gòu)造函數(shù)可以不向基類構(gòu)造函數(shù)傳遞參數(shù),也可以不聲明,構(gòu)造派生類的對(duì)象時(shí),基類的缺省構(gòu)造函數(shù)將被調(diào)用。 當(dāng)需要執(zhí)行基類中帶形參的構(gòu)造函數(shù)來初始化基類數(shù)據(jù)時(shí),派生類構(gòu)造函數(shù)應(yīng)在初始化列表中為基類構(gòu)造函數(shù)提供參數(shù)。,57,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),多繼承且有內(nèi)嵌對(duì)象時(shí)的構(gòu)造函數(shù),派生類名:派生類名(形參表):基類名1(參數(shù)), 基類名2(參數(shù)), .基類名n(參數(shù)),新增成員對(duì)象的初始化 本類成員初始化賦值語(yǔ)句; ;,58,10.6 派生

40、類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),構(gòu)造函數(shù)的執(zhí)行順序,調(diào)用基類構(gòu)造函數(shù),調(diào)用順序按照它們被繼承時(shí)聲明的順序(從左向右)。 對(duì)成員對(duì)象進(jìn)行初始化,初始化順序按照它們?cè)陬愔新暶鞯捻樞颉?執(zhí)行派生類的構(gòu)造函數(shù)體中的內(nèi)容。,59,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),60,例10-10(教材例7-4)派生類構(gòu)造函數(shù)舉例,#include using namespace std; class Base1 /基類Base1,構(gòu)造函數(shù)有參數(shù) public: Base1(int i) cout Constructing Base1 i endl; ; class Base2 /基

41、類Base2,構(gòu)造函數(shù)有參數(shù) public: Base2(int j) cout Constructing Base2 j endl; ; class Base3 /基類Base3,構(gòu)造函數(shù)無參數(shù) public: Base3() cout Constructing Base3 * endl; ;,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),61,例10-10 (續(xù)),class Derived: public Base2, public Base1, public Base3 /派生新類Derived,注意基類名的順序 public:/派生類的公有成員 Derived(int a

42、, int b, int c, int d): Base1(a), member2(d), member1(c), Base2(b) /注意基類名的個(gè)數(shù)與順序,/注意成員對(duì)象名的個(gè)數(shù)與順序 private:/派生類的私有成員對(duì)象 Base1 member1; Base2 member2; Base3 member3; ; int main() Derived obj(1, 2, 3, 4); return 0; ,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù),運(yùn)行結(jié)果: constructing Base2 2 constructing Base1 1 constructing B

43、ase3 * constructing Base1 3 constructing Base2 4 constructing Base3 *,10.6.2 拷貝構(gòu)造函數(shù),若建立派生類對(duì)象時(shí)沒有編寫拷貝構(gòu)造函數(shù),編譯器會(huì)生成一個(gè)隱含的拷貝構(gòu)造函數(shù),該函數(shù)先調(diào)用基類的拷貝構(gòu)造函數(shù),再為派生類新增的成員對(duì)象執(zhí)行拷貝。 若編寫派生類的拷貝構(gòu)造函數(shù),則需要為基類相應(yīng)的拷貝構(gòu)造函數(shù)傳遞參數(shù)。 例如: C:C(const C class Base1 /基類Base1,構(gòu)造函數(shù)有參數(shù) public: Base1(int i) cout Constructing Base1 i endl; Base1() cou

44、t Destructing Base1 endl; ; class Base2 /基類Base2,構(gòu)造函數(shù)有參數(shù) public: Base2(int j) cout Constructing Base2 j endl; Base2() cout Destructing Base2 endl; ; class Base3 /基類Base3,構(gòu)造函數(shù)無參數(shù) public: Base3() cout Constructing Base3 * endl; Base3() cout Destructing Base3 endl; ;,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.3 析構(gòu)函數(shù),65,例10

45、-11 (續(xù)),class Derived: public Base2, public Base1, public Base3 /派生新類Derived,注意基類名的順序 public:/派生類的公有成員 Derived(int a, int b, int c, int d): Base1(a), member2(d), member1(c), Base2(b) /注意基類名的個(gè)數(shù)與順序,注意成員對(duì)象名的個(gè)數(shù)與順序 private:/派生類的私有成員對(duì)象 Base1 member1; Base2 member2; Base3 member3; ; int main() Derived obj(

46、1, 2, 3, 4); return 0; ,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.3 析構(gòu)函數(shù),66,例10-11 (續(xù)),運(yùn)行結(jié)果: Constructing Base2 2 Constructing Base1 1 Constructing Base3 * Constructing Base1 3 Constructing Base2 4 Constructing Base3 * Destructing Base3 Destructing Base2 Destructing Base1 Destructing Base3 Destructing Base1 Destructing

47、 Base2,10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.3 析構(gòu)函數(shù),同名隱藏規(guī)則,當(dāng)派生類與基類中有相同成員時(shí): 若未強(qiáng)行指名,則通過派生類對(duì)象使用的是派生類中的同名成員。 如要通過派生類對(duì)象訪問基類中被隱藏的同名成員,應(yīng)使用基類名限定。,67,10.7 派生類成員的標(biāo)識(shí)與訪問 10.7.1 作用域分辨,68,例10-12(教材例7-6)多繼承同名隱藏舉例,#include using namespace std; class Base1 /定義基類Base1 public: int var; void fun() cout Member of Base1 endl; ; class Ba

48、se2 /定義基類Base2 public: int var; void fun() cout Member of Base2 endl; ; class Derived: public Base1, public Base2 /定義派生類Derived public: int var;/同名數(shù)據(jù)成員 void fun() cout Member of Derived endl; /同名函數(shù)成員 ;,10.7 派生類成員的標(biāo)識(shí)與訪問 10.7.1 作用域分辨,69,例10-12 (續(xù)),int main() Derived d; Derived *p = ,10.7 派生類成員的標(biāo)識(shí)與訪問 1

49、0.7.1 作用域分辨,二義性問題,在多繼承時(shí),基類與派生類之間,或基類之間出現(xiàn)同名成員時(shí),將出現(xiàn)訪問時(shí)的二義性(不確定性)采用虛函數(shù)(參見第8章)或同名隱藏規(guī)則來解決。 當(dāng)派生類從多個(gè)基類派生,而這些基類又從同一個(gè)基類派生,則在訪問此共同基類中的成員時(shí),將產(chǎn)生二義性采用虛基類來解決。,70,10.7 派生類成員的標(biāo)識(shí)與訪問 10.7.1 作用域分辨,二義性問題舉例,class A public: void f(); ; class B public: void f(); void g() ;,class C: public A, piblic B public: void g(); void

50、 h(); ; 如果定義:C c1; 則 c1.f() 具有二義性 而 c1.g() 無二義性(同名隱藏),71,10.7 派生類成員的標(biāo)識(shí)與訪問 10.7.1 作用域分辨,二義性的解決方法,解決方法一:用類名來限定c1.A:f() 或 c1.B:f() 解決方法二:同名隱藏在C 中聲明一個(gè)同名成員函數(shù)f(),f()再根據(jù)需要調(diào)用 A:f() 或 B:f(),72,10.7 派生類成員的標(biāo)識(shí)與訪問 10.7.1 作用域分辨,例10-13(教材例7-7)多繼承同名隱藏舉例,/7_7.cpp #include using namespace std; class Base0 /定義基類Base0

51、public: int var0; void fun0() cout Member of Base0 endl; ; class Base1: public Base0 /定義派生類Base1 public:/新增外部接口 int var1; ; class Base2: public Base0 /定義派生類Base2 public:/新增外部接口 int var2; ;,73,10.7 派生類成員的標(biāo)識(shí)與訪問 10.7.1 作用域分辨,例10-13(續(xù)),class Derived: public Base1, public Base2 /定義派生類Derived public:/新增外部

52、接口 int var; void fun() cout Member of Derived endl; ; int main() /程序主函數(shù) Derived d;/定義Derived類對(duì)象d d.Base1:var0 = 2;/使用直接基類 d.Base1:fun0(); d.Base2:var0 = 3;/使用直接基類 d.Base2:fun0(); return 0; ,74,10.7 派生類成員的標(biāo)識(shí)與訪問 10.7.1 作用域分辨,派生類C的對(duì)象的存儲(chǔ)結(jié)構(gòu)示意圖:,有二義性: Derived d; d.var0 d.Base0:var0,無二義性: d.Base1:var0 d.Base2:var0,75,10.7 派生類成員的標(biāo)識(shí)與訪問 10.7.1 作用域分辨,10.7.2 虛基類,虛基類的引入 用于有共同基類的場(chǎng)合 聲明 以virtual修飾說明基類例:class B1:virtual public B 作用 主要用來解決多繼承時(shí)可能發(fā)生的對(duì)同一基類繼承多次而產(chǎn)生的二義性問題. 為最遠(yuǎn)的派生類提供唯一的基類成員,而不重復(fù)產(chǎn)生多次拷貝 注意: 在第一級(jí)繼承時(shí)就要

溫馨提示

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