版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、計(jì)算機(jī)程序設(shè)計(jì)基礎(chǔ)第十講 類的重用與多態(tài)性教材:C+語(yǔ)言程序設(shè)計(jì)(第4版)第4章 4.4,第7章,第8章 8.3、8.4清華大學(xué) 鄭 莉目錄10.1 類的組合10.2 類的繼承與派生10.3 訪問(wèn)控制10.4 類型兼容規(guī)則10.5 多態(tài)性10.6 派生類的構(gòu)造、析構(gòu)函數(shù)10.7 派生類成員的標(biāo)識(shí)與訪問(wèn)10.8 小結(jié) 210.1.1組合 類中的成員數(shù)據(jù)是另一個(gè)類的對(duì)象。 可以在已有抽象的基礎(chǔ)上實(shí)現(xiàn)更復(fù)雜的抽象。310.1 類的組合類組合的構(gòu)造函數(shù)設(shè)計(jì) 原則:不僅要負(fù)責(zé)對(duì)本類中的基本類型成員數(shù)據(jù)賦初值,也要對(duì)對(duì)象成員初始化。 聲明形式: 類名:類名(對(duì)象成員所需的形參,本類成員形參) :對(duì)象1(參
2、數(shù)),對(duì)象2(參數(shù)),. 本類初始化 410.1 類的組合 10.1.1 組合類組合的構(gòu)造函數(shù)調(diào)用 構(gòu)造函數(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ù)即無(wú)形參的初始化 系統(tǒng)自動(dòng)生成的隱含的默認(rèn)構(gòu)造函數(shù)中,內(nèi)嵌對(duì)象全部用默認(rèn)構(gòu)造函數(shù)初始化510.1 類的組合 10.1.1 組合例10-1教材例4-4)類的組合,線段Line類/4_4.cpp#include #include using namespace std;class Point /Point類定義public:P
3、oint(int xx = 0, int yy = 0) x = xx;y = yy;Point(Point &p);int getX() return x; int getY() return y; private:int x, y;Point:Point(Point &p) /拷貝構(gòu)造函數(shù)的實(shí)現(xiàn)x = p.x;y = p.y;cout Calling the copy constructor of Point endl;610.1 類的組合 10.1.1 組合/類的組合class Line /Line類的定義public:/外部接口Line(Point xp1, Point
4、 xp2);Line(Line &l);double getLen() return len; private:/私有數(shù)據(jù)成員Point p1, p2;/Point類的對(duì)象p1,p2double len;/組合類的構(gòu)造函數(shù)Line:Line(Point xp1, Point xp2) : p1(xp1), p2(xp2) cout Calling constructor of Line endl;double x = static_cast(p1.getX() - p2.getX();double y = static_cast(p1.getY() - p2.getY();len =
5、sqrt(x * x + y * y);Line:Line (Line &l): p1(l.p1), p2(l.p2) /組合類的拷貝構(gòu)造函數(shù)cout Calling the copy constructor of Line endl;len = l.len;710.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 o
6、f the line is: ;cout line.getLen() endl;cout The length of the line2 is: ;cout line2.getLen() 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_H10.3 訪問(wèn)控制 10.3.1 公有繼承23例10-2 (續(xù))
7、/Rectangle.h#ifndef _RECTANGLE_H#define _RECTANGLE_H#include Point.hclass 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ù)
8、成員float w, h;#endif /_RECTANGLE_H10.3 訪問(wèn)控制 10.3.1 公有繼承24例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()
9、, rect.getH() 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_H10.3 訪問(wèn)控制 10.3.2 私有繼承27例10-3 (續(xù))/Rectangle.h#ifndef _RECTANGLE_H#define _RECTANGLE_H#include Point.hclass Rectan
10、gle: 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 Point:getX(); float getY() const return Point:getY(); float getH() co
11、nst return h; float getW() const return w; private:/新增私有數(shù)據(jù)成員float w, h;#endif /_RECTANGLE_H10.3 訪問(wèn)控制 10.3.2 私有繼承28例10-3 (續(xù))#include #include using namespace std;int main() Rectangle rect;/定義Rectangle類的對(duì)象rect.initRectangle(2, 3, 20, 10); /設(shè)置矩形的數(shù)據(jù)rect.move(3,2);/移動(dòng)矩形位置cout The data of rect(x,y,w,h): e
12、ndl;cout rect.getX() , /輸出矩形的特征參數(shù) rect.getY() , rect.getW() , rect.getH() endl;return 0;10.3 訪問(wèn)控制 10.3.2 私有繼承10.3.3 保護(hù)繼承(protected) 基類的public和protected成員都以protected身份出現(xiàn)在派生類中,但基類的private成員不可直接訪問(wèn)。 派生類中的成員函數(shù)可以直接訪問(wèn)基類中的public和protected成員,但不能直接訪問(wèn)基類的private成員。 通過(guò)派生類的對(duì)象不能直接訪問(wèn)基類中的任何成員2910.3 訪問(wèn)控制 10.3.3 保護(hù)繼承p
13、rotected 成員的特點(diǎn)與作用 對(duì)建立其所在類對(duì)象的模塊來(lái)說(shuō),它與 private 成員的性質(zhì)相同。 對(duì)于其派生類來(lái)說(shuō),它與 public 成員的性質(zhì)相同。 既實(shí)現(xiàn)了數(shù)據(jù)隱藏,又方便繼承,實(shí)現(xiàn)代碼重用。3010.3 訪問(wèn)控制 10.3.3 保護(hù)繼承31例: protected 成員舉例class A protected:int x;int main() A a;a.x = 5; /錯(cuò)誤10.3 訪問(wèn)控制 10.3.3 保護(hù)繼承32例 (續(xù))class A protected:int x;class B: public Apublic:void function();void B:funct
14、ion() x = 5; /正確10.3 訪問(wèn)控制 10.3.3 保護(hù)繼承10.4 類型兼容規(guī)則 一個(gè)公有派生類的對(duì)象在使用上可以被當(dāng)作基類的對(duì)象,反之則禁止。具體表現(xiàn)在: 派生類的對(duì)象可以隱含轉(zhuǎn)換為基類對(duì)象。 派生類的對(duì)象可以初始化基類的引用。 派生類的指針可以隱含轉(zhuǎn)換為基類的指針。 通過(guò)基類對(duì)象名、指針只能使用從基類繼承的成員3310.4 類型兼容規(guī)則34例10-4教材例7-3)類型兼容規(guī)則舉例#include using namespace std;class Base1 /基類Base1定義public:void display() const cout Base1:display()
15、 endl;class Base2: public Base1 /公有派生類Base2定義public:void display() const cout Base2:display() endl;class Derived: public Base2 /公有派生類Derived定義public:void display() const cout Derived:display() display();/對(duì)象指針-成員名int main() /主函數(shù)Base1 base1;/聲明Base1類對(duì)象Base2 base2;/聲明Base2類對(duì)象Derived derived;/聲明Derived類
16、對(duì)象fun(&base1);/用Base1對(duì)象的指針調(diào)用fun函數(shù)fun(&base2);/用Base2對(duì)象的指針調(diào)用fun函數(shù)fun(&derived); /用Derived對(duì)象的指針調(diào)用fun函數(shù)return 0;10.4 類型兼容規(guī)則運(yùn)行結(jié)果:Base1:display()Base1:display()Base1:display()絕對(duì)不要重新定義繼承而來(lái)的非虛函數(shù)10.5.1 一般虛函數(shù)成員 C+中引入了虛函數(shù)的機(jī)制在派生類中可以對(duì)基類中的成員函數(shù)進(jìn)行覆蓋重定義)。 虛函數(shù)的聲明Virtual 函數(shù)類型 函數(shù)名形參表) 函數(shù)體3610.5 多態(tài)性例10-5教材例
17、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 /公有派生類Base2定義public:void display() const; /覆蓋基類的虛函數(shù);void Base2:display() const cout Base2:display() endl;3710.5 多態(tài)性 10.5.1
18、 一般虛函數(shù)成員 class Derived: public Base2 /公有派生類public:void display() const; /覆蓋基類的虛函數(shù);void Derived:display() const cout Derived:display() display();/對(duì)象指針-成員名 int main() /主函數(shù)Base1 base1;/定義Base1類對(duì)象Base2 base2;/定義Base2類對(duì)象Derived derived; /定義Derived類對(duì)象fun(&base1);/用Base1對(duì)象的指針調(diào)用fun函數(shù)fun(&base2);/用Ba
19、se2對(duì)象的指針調(diào)用fun函數(shù)fun(&derived);/用Derived對(duì)象的指針調(diào)用fun函數(shù)return 0;38例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ù)?可能通過(guò)基類指針刪除派生類對(duì)象;如果你打算允許其他人通過(guò)基類指針調(diào)用對(duì)象的析構(gòu)函數(shù)通過(guò)delete這樣做是正常的),就需要讓基類的析構(gòu)函數(shù)成為虛函數(shù),否則執(zhí)行delete的結(jié)果是不確定的。3910.5 多態(tài)性例10-6教材例8-5虛析構(gòu)函數(shù)舉例#includ
20、e using namespace std; class Base public:Base();Base:Base() cout Base destructor endl; class Derived: public Basepublic:Derived();Derived();4010.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 p; void fun(Base* b) delete b; int
21、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 destructor4110.5 多態(tài)性 10.5.2 虛析構(gòu)函數(shù)42指向f()的指針指向g()的指針Base的虛表指向f()的指針指向g()的指針指向h()的指針Derived的虛表(Base:f的代碼)push %ebpmov %esp,%ebp(Base:g的代碼)push %ebpmov %esp,%ebp(Derive
22、d:f的代碼)push %ebpmov %esp,%ebp(Derived:h的代碼)push %ebpmov %esp,%ebpivptrivptrjBase類型對(duì)象Derived類型對(duì)象class Base public:virtual void f();virtual void g();private:int i;class Derived: public Base public:virtual void f(); /覆蓋Base:fvirtual 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ù)
23、純虛函數(shù)是一個(gè)在基類中聲明的虛函數(shù),它在該基類中沒(méi)有定義具體的操作內(nèi)容,要求各派生類根據(jù)實(shí)際需要定義自己的版本,純虛函數(shù)的聲明格式為: virtual 函數(shù)類型 函數(shù)名(參數(shù)表) = 0; 帶有純虛函數(shù)的類稱為抽象類: class 類名 virtual 類型 函數(shù)名(參數(shù)表)=0; /純虛函數(shù) . 4310.5 多態(tài)性10.5.5 抽象類 作用 抽象類為抽象和設(shè)計(jì)的目的而聲明,將有關(guān)的數(shù)據(jù)和行為組織在一個(gè)繼承層次結(jié)構(gòu)中,保證派生類具有要求的行為。 對(duì)于暫時(shí)無(wú)法實(shí)現(xiàn)的函數(shù),可以聲明為純虛函數(shù),留給派生類去實(shí)現(xiàn)。 注意 抽象類只能作為基類來(lái)使用。 不能聲明抽象類的對(duì)象。 構(gòu)造函數(shù)不能是虛函數(shù),析構(gòu)
24、函數(shù)可以是虛函數(shù)。4410.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 Base2: public Base1 /公有派生類Base2定義public:void display() const;/覆蓋基類的虛函數(shù);void Base2:display() const cout Base2:display() endl;4510.5 多態(tài)性 10.5.5 抽象類class D
25、erived: public Base2 /公有派生類Derived定義public:void display() const;/覆蓋基類的虛函數(shù);void Derived:display() const cout Derived:display() display();/對(duì)象指針-成員名 int main() /主函數(shù)Base2 base2;/定義Base2類對(duì)象Derived derived;/定義Derived類對(duì)象fun(&base2);/用Base2對(duì)象的指針調(diào)用fun函數(shù)fun(&derived);/用Derived對(duì)象的指針調(diào)用fun函數(shù)return 0;4610
26、.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ù)派生新的類。4710.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)多繼承時(shí)派生類的聲明class 派生類名:繼承方式1 基類名1,繼承方式2 基類名2,.成員聲明;注意:每一個(gè)“繼承方式”,只用于限制對(duì)緊隨其后之基類的繼承。4810.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)例10-8多繼承舉例
27、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() const;private const:int c;4910.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)例10-8 (續(xù))void A:setA(int x) a=x; void B:set
28、B(int x) b=x; void C:setC(int x, int y, int z) /派生類成員直接訪問(wèn)基類的/公有成員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ò)誤/ obj.showB(); 錯(cuò)誤return 0;5010.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)行初始
29、化,對(duì)繼承來(lái)的基類成員的初始化,自動(dòng)調(diào)用基類構(gòu)造函數(shù)完成。 派生類的構(gòu)造函數(shù)需要給基類的構(gòu)造函數(shù)傳遞參數(shù)5110.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)單一繼承時(shí)的構(gòu)造函數(shù)派生類名:派生類名(基類所需的形參,本類成員所需的形參):基類名(參數(shù)表)本類成員初始化賦值語(yǔ)句;5210.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)53例10-9單一繼承時(shí)的構(gòu)造函數(shù)舉例#includeusing namecpace std;class B public:B();B(int i);B();void print() const;private:int b;10.6 派生類的構(gòu)造和析構(gòu)函數(shù)
30、10.6.1 構(gòu)造函數(shù)54例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 called. endl;void B:print() const cout b endl;10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)55例10-9 (續(xù))class C: public B public:C();C(int i, int j);C();void print() const;p
31、rivate: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;10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)56例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 派生類
32、的構(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ǔ)句;5710.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ù)來(lái)初始化基類數(shù)據(jù)時(shí),派生類構(gòu)造函數(shù)應(yīng)在初始化列表中為基類構(gòu)造函數(shù)提供參數(shù)。5810.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10
33、.6.1 構(gòu)造函數(shù)多繼承且有內(nèi)嵌對(duì)象時(shí)的構(gòu)造函數(shù)派生類名:派生類名(形參表):基類名1(參數(shù)), 基類名2(參數(shù)), .基類名n(參數(shù)),新增成員對(duì)象的初始化 本類成員初始化賦值語(yǔ)句;5910.6 派生類的構(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)容。6010.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)61例10-10教材例7-4)派生類構(gòu)造函數(shù)舉例#include using namespace std;class Bas
34、e1 /基類Base1,構(gòu)造函數(shù)有參數(shù)public:Base1(int i) cout Constructing Base1 i endl; ;class Base2 /基類Base2,構(gòu)造函數(shù)有參數(shù)public:Base2(int j) cout Constructing Base2 j endl; ;class Base3 /基類Base3,構(gòu)造函數(shù)無(wú)參數(shù)public:Base3() cout Constructing Base3 * endl; ;10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)62例10-10 (續(xù))class Derived: public Base2, pu
35、blic 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(1, 2, 3, 4);return 0;10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造
36、函數(shù)運(yùn)行結(jié)果:constructing Base2 2constructing Base1 1constructing Base3 *constructing Base1 3constructing Base2 4constructing Base3 *10.6.2 拷貝構(gòu)造函數(shù) 若建立派生類對(duì)象時(shí)沒(méi)有編寫拷貝構(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 &c1): B(c1) 6310.6 派生類的構(gòu)造和析構(gòu)函數(shù)10.
37、6.3 析構(gòu)函數(shù) 析構(gòu)函數(shù)也不被繼承,派生類自行聲明 聲明方法與一般無(wú)繼承關(guān)系時(shí)類的析構(gòu)函數(shù)相同。 不需要顯式地調(diào)用基類的析構(gòu)函數(shù),系統(tǒng)會(huì)自動(dòng)隱式調(diào)用。 析構(gòu)函數(shù)的調(diào)用次序與構(gòu)造函數(shù)相反。6410.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.3 析構(gòu)函數(shù)65例10-11教材例7-5)派生類析構(gòu)函數(shù)舉例#include using namespace std;class Base1 /基類Base1,構(gòu)造函數(shù)有參數(shù)public:Base1(int i) cout Constructing Base1 i endl; Base1() cout Destructing Base1 endl; ;class
38、 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ù)無(wú)參數(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ù)66例10-11 (續(xù))class Derived: public Base2, publi
39、c 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(1, 2, 3, 4);return 0;10.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.3 析構(gòu)函數(shù)67
40、例10-11 (續(xù))運(yùn)行結(jié)果:Constructing Base2 2Constructing Base1 1Constructing Base3 *Constructing Base1 3Constructing Base2 4Constructing Base3 *Destructing Base3Destructing Base2Destructing Base1Destructing Base3Destructing Base1Destructing Base210.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.3 析構(gòu)函數(shù)同名隱藏規(guī)則當(dāng)派生類與基類中有相同成員時(shí):若未強(qiáng)行指名,則通過(guò)派生類對(duì)
41、象使用的是派生類中的同名成員。如要通過(guò)派生類對(duì)象訪問(wèn)基類中被隱藏的同名成員,應(yīng)使用基類名限定。6810.7 派生類成員的標(biāo)識(shí)與訪問(wèn) 10.7.1 作用域分辨69例10-12教材例7-6)多繼承同名隱藏舉例#include using namespace std;class Base1 /定義基類Base1public:int var;void fun() cout Member of Base1 endl; ;class Base2 /定義基類Base2public:int var;void fun() cout Member of Base2 endl; ;class Derived: pu
42、blic Base1, public Base2 /定義派生類Derivedpublic:int var;/同名數(shù)據(jù)成員void fun() cout Member of Derived Base2:var = 3; /作用域分辨符標(biāo)識(shí)p-Base2:fun();/訪問(wèn)Base2基類成員return 0;10.7 派生類成員的標(biāo)識(shí)與訪問(wèn) 10.7.1 作用域分辨二義性問(wèn)題 在多繼承時(shí),基類與派生類之間,或基類之間出現(xiàn)同名成員時(shí),將出現(xiàn)訪問(wèn)時(shí)的二義性不確定性)采用虛函數(shù)參見(jiàn)第8章或同名隱藏規(guī)則來(lái)解決。 當(dāng)派生類從多個(gè)基類派生,而這些基類又從同一個(gè)基類派生,則在訪問(wèn)此共同基類中的成員時(shí),將產(chǎn)生二義
43、性采用虛基類來(lái)解決。7110.7 派生類成員的標(biāo)識(shí)與訪問(wèn) 10.7.1 作用域分辨二義性問(wèn)題舉例class A public:void f();class B public:void f();void g();class C: public A, piblic B public:void g();void h();如果定義:C c1;那么 c1.f() 具有二義性而 c1.g() 無(wú)二義性同名隱藏)7210.7 派生類成員的標(biāo)識(shí)與訪問(wèn) 10.7.1 作用域分辨二義性的解決方法 解決方法一:用類名來(lái)限定c1.A:f() 或 c1.B:f() 解決方法二:同名隱藏在C 中聲明一個(gè)同名成員函數(shù)f()
44、,f()再根據(jù)需要調(diào)用 A:f() 或 B:f()7310.7 派生類成員的標(biāo)識(shí)與訪問(wèn) 10.7.1 作用域分辨例10-13教材例7-7)多繼承同名隱藏舉例/7_7.cpp#include using namespace std;class Base0 /定義基類Base0public:int var0;void fun0() cout Member of Base0 endl; ;class Base1: public Base0 /定義派生類Base1 public:/新增外部接口int var1;class Base2: public Base0 /定義派生類Base2 public:/
45、新增外部接口int var2;7410.7 派生類成員的標(biāo)識(shí)與訪問(wèn) 10.7.1 作用域分辨例10-13續(xù))class Derived: public Base1, public Base2 /定義派生類Derived public:/新增外部接口int var;void fun() cout Member of Derived endl; ; int main() /程序主函數(shù)Derived d;/定義Derived類對(duì)象dd.Base1:var0 = 2;/使用直接基類d.Base1:fun0();d.Base2:var0 = 3;/使用直接基類d.Base2:fun0();return
46、0;7510.7 派生類成員的標(biāo)識(shí)與訪問(wèn) 10.7.1 作用域分辨派生類C的對(duì)象的存儲(chǔ)結(jié)構(gòu)示意圖:var0var1var0var2varBase0類成員Base0類成員Base1類成員Base2類成員Derived類對(duì)象有二義性:有二義性:Derived d;d.var0d.Base0:var0無(wú)二義性:無(wú)二義性:d.Base1:var0d.Base2:var07610.7 派生類成員的標(biāo)識(shí)與訪問(wèn) 10.7.1 作用域分辨Base0Base1Base2DerivedBase010.7.2 虛基類 虛基類的引入 用于有共同基類的場(chǎng)合 聲明 以virtual修飾說(shuō)明基類例:class B1:vir
47、tual public B 作用 主要用來(lái)解決多繼承時(shí)可能發(fā)生的對(duì)同一基類繼承多次而產(chǎn)生的二義性問(wèn)題. 為最遠(yuǎn)的派生類提供唯一的基類成員,而不重復(fù)產(chǎn)生多次拷貝 注意: 在第一級(jí)繼承時(shí)就要將共同基類設(shè)計(jì)為虛基類。7710.7 派生類成員的標(biāo)識(shí)與訪問(wèn)78例10-14教材例7-8)虛基類舉例10.7 派生類成員的標(biāo)識(shí)與訪問(wèn) 10.7.2 虛基類DerivedBase0:var0:intBase1:var1:intBase2:var2:intvar :intBase0:fun0():voidfun():voidBase1+ var1 : intBase2+ var2 : intDerived+ var : int+ fun() : void Base0+ var0 : int+ fun0() : void79例10-14 (續(xù))#include usin
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024個(gè)人民間借款合同范本格式
- 2024年度家具搬運(yùn)與安裝合同
- 職業(yè)危害課件教學(xué)課件
- 2024年建筑工程抹灰班組承包合同
- 2024年度財(cái)務(wù)咨詢與審計(jì)服務(wù)協(xié)議
- 煙花創(chuàng)意課件教學(xué)課件
- 2024健身器材代銷合同
- 2024年度汽車銷售代理協(xié)議
- 2024年度環(huán)保項(xiàng)目工程咨詢服務(wù)合同
- 2024品牌授權(quán)與加盟合作協(xié)議
- 武術(shù)隊(duì)管理制度
- 秋冬季常見(jiàn)傳染病預(yù)防知識(shí)培訓(xùn)
- 群眾文化活動(dòng)服務(wù)投標(biāo)方案(技術(shù)標(biāo))
- 通信行業(yè)銷售人員銷售技巧培訓(xùn)
- 2024建筑門窗安裝技術(shù)規(guī)程
- 降低會(huì)陰側(cè)切率的PDCA
- 第二篇?jiǎng)?chuàng)業(yè)機(jī)會(huì)的識(shí)別課件
- 2023年江蘇省無(wú)錫錫山區(qū)市場(chǎng)監(jiān)督管理局招聘11人筆試參考題庫(kù)(共500題)答案詳解版
- 《危機(jī)概述》課件
- 浙江省寧波市鎮(zhèn)海區(qū)蛟川書院2023-2024學(xué)年九年級(jí)上學(xué)期期中科學(xué)試卷
- 54設(shè)計(jì)和開(kāi)發(fā)驗(yàn)證記錄表
評(píng)論
0/150
提交評(píng)論