版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、計算機程序設(shè)計基礎(chǔ)第十講 類的重用與多態(tài)性教材:C+語言程序設(shè)計(第4版)第4章 4.4,第7章,第8章 8.3、8.4清華大學(xué) 鄭 莉目錄10.1 類的組合10.2 類的繼承與派生10.3 訪問控制10.4 類型兼容規(guī)則10.5 多態(tài)性10.6 派生類的構(gòu)造、析構(gòu)函數(shù)10.7 派生類成員的標識與訪問10.8 小結(jié) 210.1.1組合 類中的成員數(shù)據(jù)是另一個類的對象。 可以在已有抽象的基礎(chǔ)上實現(xiàn)更復(fù)雜的抽象。310.1 類的組合類組合的構(gòu)造函數(shù)設(shè)計 原則:不僅要負責對本類中的基本類型成員數(shù)據(jù)賦初值,也要對對象成員初始化。 聲明形式: 類名:類名(對象成員所需的形參,本類成員形參) :對象1(參
2、數(shù)),對象2(參數(shù)),. 本類初始化 410.1 類的組合 10.1.1 組合類組合的構(gòu)造函數(shù)調(diào)用 構(gòu)造函數(shù)調(diào)用順序:先調(diào)用內(nèi)嵌對象的構(gòu)造函數(shù)按內(nèi)嵌時的聲明順序,先聲明者先構(gòu)造)。然后調(diào)用本類的構(gòu)造函數(shù)。(析構(gòu)函數(shù)的調(diào)用順序相反) 初始化列表中未出現(xiàn)的內(nèi)嵌對象,用默認構(gòu)造函數(shù)即無形參的初始化 系統(tǒng)自動生成的隱含的默認構(gòu)造函數(shù)中,內(nèi)嵌對象全部用默認構(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ù)的實現(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類的對象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類的對象Line line(myp1, myp2);/建立Line類的對象Line line2(line);/利用拷貝構(gòu)造函數(shù)建立一個新對象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 訪問控制 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 訪問控制 10.3.1 公有繼承24例10-2 (續(xù))#include #include using namespace std;int main() Rectangle rect;/定義Rectangle類的對象/設(shè)置矩形的數(shù)據(jù)rect.initRectangle(2, 3, 20, 10);rect.move(3,2);/移動矩形位置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 訪問控制 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 訪問控制 10.3.2 私有繼承28例10-3 (續(xù))#include #include using namespace std;int main() Rectangle rect;/定義Rectangle類的對象rect.initRectangle(2, 3, 20, 10); /設(shè)置矩形的數(shù)據(jù)rect.move(3,2);/移動矩形位置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 訪問控制 10.3.2 私有繼承10.3.3 保護繼承(protected) 基類的public和protected成員都以protected身份出現(xiàn)在派生類中,但基類的private成員不可直接訪問。 派生類中的成員函數(shù)可以直接訪問基類中的public和protected成員,但不能直接訪問基類的private成員。 通過派生類的對象不能直接訪問基類中的任何成員2910.3 訪問控制 10.3.3 保護繼承p
13、rotected 成員的特點與作用 對建立其所在類對象的模塊來說,它與 private 成員的性質(zhì)相同。 對于其派生類來說,它與 public 成員的性質(zhì)相同。 既實現(xiàn)了數(shù)據(jù)隱藏,又方便繼承,實現(xiàn)代碼重用。3010.3 訪問控制 10.3.3 保護繼承31例: protected 成員舉例class A protected:int x;int main() A a;a.x = 5; /錯誤10.3 訪問控制 10.3.3 保護繼承32例 (續(xù))class A protected:int x;class B: public Apublic:void function();void B:funct
14、ion() x = 5; /正確10.3 訪問控制 10.3.3 保護繼承10.4 類型兼容規(guī)則 一個公有派生類的對象在使用上可以被當作基類的對象,反之則禁止。具體表現(xiàn)在: 派生類的對象可以隱含轉(zhuǎn)換為基類對象。 派生類的對象可以初始化基類的引用。 派生類的指針可以隱含轉(zhuǎn)換為基類的指針。 通過基類對象名、指針只能使用從基類繼承的成員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();/對象指針-成員名int main() /主函數(shù)Base1 base1;/聲明Base1類對象Base2 base2;/聲明Base2類對象Derived derived;/聲明Derived類
16、對象fun(&base1);/用Base1對象的指針調(diào)用fun函數(shù)fun(&base2);/用Base2對象的指針調(diào)用fun函數(shù)fun(&derived); /用Derived對象的指針調(diào)用fun函數(shù)return 0;10.4 類型兼容規(guī)則運行結(jié)果:Base1:display()Base1:display()Base1:display()絕對不要重新定義繼承而來的非虛函數(shù)10.5.1 一般虛函數(shù)成員 C+中引入了虛函數(shù)的機制在派生類中可以對基類中的成員函數(shù)進行覆蓋重定義)。 虛函數(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();/對象指針-成員名 int main() /主函數(shù)Base1 base1;/定義Base1類對象Base2 base2;/定義Base2類對象Derived derived; /定義Derived類對象fun(&base1);/用Base1對象的指針調(diào)用fun函數(shù)fun(&base2);/用Ba
19、se2對象的指針調(diào)用fun函數(shù)fun(&derived);/用Derived對象的指針調(diào)用fun函數(shù)return 0;38例10-5續(xù))10.5 多態(tài)性 10.5.1 一般虛函數(shù)成員 運行結(jié)果:Base1:display()Base2:display()Derived:display()10.5.2 虛析構(gòu)函數(shù)為什么需要虛析構(gòu)函數(shù)?可能通過基類指針刪除派生類對象;如果你打算允許其他人通過基類指針調(diào)用對象的析構(gòu)函數(shù)通過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ù)) 運行時結(jié)果: Base destructor 避免上述錯誤的有效方法就是將析構(gòu)函數(shù)聲明為虛函數(shù),運行結(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類型對象Derived類型對象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ù)動態(tài)綁定的實現(xiàn)原理10.5.4 純虛函數(shù)
23、純虛函數(shù)是一個在基類中聲明的虛函數(shù),它在該基類中沒有定義具體的操作內(nèi)容,要求各派生類根據(jù)實際需要定義自己的版本,純虛函數(shù)的聲明格式為: virtual 函數(shù)類型 函數(shù)名(參數(shù)表) = 0; 帶有純虛函數(shù)的類稱為抽象類: class 類名 virtual 類型 函數(shù)名(參數(shù)表)=0; /純虛函數(shù) . 4310.5 多態(tài)性10.5.5 抽象類 作用 抽象類為抽象和設(shè)計的目的而聲明,將有關(guān)的數(shù)據(jù)和行為組織在一個繼承層次結(jié)構(gòu)中,保證派生類具有要求的行為。 對于暫時無法實現(xiàn)的函數(shù),可以聲明為純虛函數(shù),留給派生類去實現(xiàn)。 注意 抽象類只能作為基類來使用。 不能聲明抽象類的對象。 構(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();/對象指針-成員名 int main() /主函數(shù)Base2 base2;/定義Base2類對象Derived derived;/定義Derived類對象fun(&base2);/用Base2對象的指針調(diào)用fun函數(shù)fun(&derived);/用Derived對象的指針調(diào)用fun函數(shù)return 0;4610
26、.5 多態(tài)性 10.5.5 抽象類例10-7續(xù))運行結(jié)果:Base2:display()Derived:display()基類與派生類的對應(yīng)關(guān)系 單繼承 派生類只從一個基類派生。 多繼承 派生類從多個基類派生。 多重派生 由一個基類派生出多個不同的派生類。 多層派生 派生類又作為基類,繼續(xù)派生新的類。4710.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)多繼承時派生類的聲明class 派生類名:繼承方式1 基類名1,繼承方式2 基類名2,.成員聲明;注意:每一個“繼承方式”,只用于限制對緊隨其后之基類的繼承。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) /派生類成員直接訪問基類的/公有成員setA(x); setB(y); c = z;/其他函數(shù)實現(xiàn)略int main() C obj;obj.setA(5);obj.showA();obj.setC(6,7,9);obj.showC();/ obj.setB(6); 錯誤/ obj.showB(); 錯誤return 0;5010.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)繼承時的構(gòu)造函數(shù) 基類的構(gòu)造函數(shù)不被繼承,派生類中需要聲明自己的構(gòu)造函數(shù)。 定義構(gòu)造函數(shù)時,只需要對本類中新增成員進行初始
29、化,對繼承來的基類成員的初始化,自動調(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ù)單一繼承時的構(gòu)造函數(shù)派生類名:派生類名(基類所需的形參,本類成員所需的形參):基類名(參數(shù)表)本類成員初始化賦值語句;5210.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)53例10-9單一繼承時的構(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ù)多繼承時的構(gòu)造函數(shù)派生類名:派生類名(參數(shù)表):基類名1(基類1初始化參數(shù)表), 基類名2(基類2初始化參數(shù)表), .基類名n(基類n初始化參數(shù)表) 本類成員初始化賦值語句;5710.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)派生類與基類的構(gòu)造函數(shù) 當基類中聲明有缺省構(gòu)造函數(shù)或未聲明構(gòu)造函數(shù)時,派生類構(gòu)造函數(shù)可以不向基類構(gòu)造函數(shù)傳遞參數(shù),也可以不聲明,構(gòu)造派生類的對象時,基類的缺省構(gòu)造函數(shù)將被調(diào)用。 當需要執(zhí)行基類中帶形參的構(gòu)造函數(shù)來初始化基類數(shù)據(jù)時,派生類構(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)嵌對象時的構(gòu)造函數(shù)派生類名:派生類名(形參表):基類名1(參數(shù)), 基類名2(參數(shù)), .基類名n(參數(shù)),新增成員對象的初始化 本類成員初始化賦值語句;5910.6 派生類的構(gòu)造和析構(gòu)函數(shù) 10.6.1 構(gòu)造函數(shù)構(gòu)造函數(shù)的執(zhí)行順序調(diào)用基類構(gòu)造函數(shù),調(diào)用順序按照它們被繼承時聲明的順序從左向右)。對成員對象進行初始化,初始化順序按照它們在類中聲明的順序。執(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ù)無參數(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) /注意基類名的個數(shù)與順序,/注意成員對象名的個數(shù)與順序private:/派生類的私有成員對象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ù)運行結(jié)果:constructing Base2 2constructing Base1 1constructing Base3 *constructing Base1 3constructing Base2 4constructing Base3 *10.6.2 拷貝構(gòu)造函數(shù) 若建立派生類對象時沒有編寫拷貝構(gòu)造函數(shù),編譯器會生成一個隱含的拷貝構(gòu)造函數(shù),該函數(shù)先調(diào)用基類的拷貝構(gòu)造函數(shù),再為派生類新增的成員對象執(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ù)也不被繼承,派生類自行聲明 聲明方法與一般無繼承關(guān)系時類的析構(gòu)函數(shù)相同。 不需要顯式地調(diào)用基類的析構(gòu)函數(shù),系統(tǒ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ù)無參數(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) /注意基類名的個數(shù)與順序,注意成員對象名的個數(shù)與順序private:/派生類的私有成員對象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ù))運行結(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ī)則當派生類與基類中有相同成員時:若未強行指名,則通過派生類對
41、象使用的是派生類中的同名成員。如要通過派生類對象訪問基類中被隱藏的同名成員,應(yīng)使用基類名限定。6810.7 派生類成員的標識與訪問 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; /作用域分辨符標識p-Base2:fun();/訪問Base2基類成員return 0;10.7 派生類成員的標識與訪問 10.7.1 作用域分辨二義性問題 在多繼承時,基類與派生類之間,或基類之間出現(xiàn)同名成員時,將出現(xiàn)訪問時的二義性不確定性)采用虛函數(shù)參見第8章或同名隱藏規(guī)則來解決。 當派生類從多個基類派生,而這些基類又從同一個基類派生,則在訪問此共同基類中的成員時,將產(chǎn)生二義
43、性采用虛基類來解決。7110.7 派生類成員的標識與訪問 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 h();如果定義:C c1;那么 c1.f() 具有二義性而 c1.g() 無二義性同名隱藏)7210.7 派生類成員的標識與訪問 10.7.1 作用域分辨二義性的解決方法 解決方法一:用類名來限定c1.A:f() 或 c1.B:f() 解決方法二:同名隱藏在C 中聲明一個同名成員函數(shù)f()
44、,f()再根據(jù)需要調(diào)用 A:f() 或 B:f()7310.7 派生類成員的標識與訪問 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 派生類成員的標識與訪問 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類對象dd.Base1:var0 = 2;/使用直接基類d.Base1:fun0();d.Base2:var0 = 3;/使用直接基類d.Base2:fun0();return
46、0;7510.7 派生類成員的標識與訪問 10.7.1 作用域分辨派生類C的對象的存儲結(jié)構(gòu)示意圖:var0var1var0var2varBase0類成員Base0類成員Base1類成員Base2類成員Derived類對象有二義性:有二義性:Derived d;d.var0d.Base0:var0無二義性:無二義性:d.Base1:var0d.Base2:var07610.7 派生類成員的標識與訪問 10.7.1 作用域分辨Base0Base1Base2DerivedBase010.7.2 虛基類 虛基類的引入 用于有共同基類的場合 聲明 以virtual修飾說明基類例:class B1:vir
47、tual public B 作用 主要用來解決多繼承時可能發(fā)生的對同一基類繼承多次而產(chǎn)生的二義性問題. 為最遠的派生類提供唯一的基類成員,而不重復(fù)產(chǎn)生多次拷貝 注意: 在第一級繼承時就要將共同基類設(shè)計為虛基類。7710.7 派生類成員的標識與訪問78例10-14教材例7-8)虛基類舉例10.7 派生類成員的標識與訪問 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. 本站所有資源如無特殊說明,都需要本地電腦安裝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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五版高科技創(chuàng)業(yè)企業(yè)合伙人利益共享協(xié)議3篇
- 二零二五年度出租車行業(yè)數(shù)據(jù)共享與司機權(quán)益保護合同3篇
- 2025年分公司設(shè)立及業(yè)務(wù)培訓(xùn)合作協(xié)議書4篇
- 二零二五年度臨時職工技能提升培訓(xùn)合同
- 2025年度陶瓷設(shè)計工作室設(shè)計師勞動合同樣本
- 萬科星辰大廈2024年施工總承包合同版
- 二零二五年度城市地下空間開發(fā)土石方運輸與管網(wǎng)鋪設(shè)合同3篇
- 二零二五年度廠房租賃合同附安全風(fēng)險評估協(xié)議3篇
- 二手房定金合同參考模板(2024版)
- 2025年門窗行業(yè)供應(yīng)鏈戰(zhàn)略合作框架協(xié)議
- 南安市第三次全國文物普查不可移動文物-各鄉(xiāng)鎮(zhèn)、街道分布情況登記清單(表五)
- 選煤廠安全知識培訓(xùn)課件
- 項目前期選址分析報告
- 急性肺栓塞搶救流程
- 《統(tǒng)計學(xué)-基于Python》 課件全套 第1-11章 數(shù)據(jù)與Python語言-時間序列分析和預(yù)測
- 《形象價值百萬》課件
- 紅色文化教育國內(nèi)外研究現(xiàn)狀范文十
- 中醫(yī)基礎(chǔ)理論-肝
- 小學(xué)外來人員出入校門登記表
- 《土地利用規(guī)劃學(xué)》完整課件
- GB/T 25283-2023礦產(chǎn)資源綜合勘查評價規(guī)范
評論
0/150
提交評論