




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、1第十一章第十一章 類的其它特性類的其它特性 2友元函數(shù)友元函數(shù)類中私有和保護(hù)的成員在類外不能被訪問。類中私有和保護(hù)的成員在類外不能被訪問。友元函數(shù)是一種定義在類外部的友元函數(shù)是一種定義在類外部的普通函普通函數(shù)數(shù),其特點(diǎn)是,其特點(diǎn)是能夠訪問類中私有成員和能夠訪問類中私有成員和保護(hù)成員保護(hù)成員,即類的訪問權(quán)限的限制對其,即類的訪問權(quán)限的限制對其不起作用。不起作用。3友元函數(shù)需要在友元函數(shù)需要在類體內(nèi)類體內(nèi)進(jìn)行說明,在前面加進(jìn)行說明,在前面加上關(guān)鍵字上關(guān)鍵字friend。一般格式為:一般格式為:friend FuncName();friend float Volume(A &a);關(guān)鍵字關(guān)
2、鍵字返回值類型返回值類型函數(shù)名函數(shù)名函數(shù)參數(shù)函數(shù)參數(shù)4友元函數(shù)不是成員函數(shù)友元函數(shù)不是成員函數(shù),用法也與普通,用法也與普通的函數(shù)完全一致,的函數(shù)完全一致,只不過它能訪問類中只不過它能訪問類中所有的數(shù)據(jù)所有的數(shù)據(jù)。友元函數(shù)破壞了類的封裝友元函數(shù)破壞了類的封裝性和隱蔽性,使得非成員函數(shù)可以訪問性和隱蔽性,使得非成員函數(shù)可以訪問類的私有成員類的私有成員。一個類的友元可以自由地用該類中的所有成員。一個類的友元可以自由地用該類中的所有成員。5class Afloat x,y;public: A(float a, float b) x=a; y=b; float Sum() return x+y; fri
3、end float Sum(A &a) return a.x+a.y; ;void 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ù)6有關(guān)友元函數(shù)的使用,說明如下:有關(guān)友元函數(shù)的使用,說明如下:友元函數(shù)不是類的成員函數(shù)友元函數(shù)不是類的成員函數(shù)友元函數(shù)近似于友元函數(shù)近似于普通的函數(shù)
4、普通的函數(shù),它不帶有,它不帶有this指針,指針,因此必須將對象名或?qū)ο蟮囊米鳛橐虼吮仨殞ο竺驅(qū)ο蟮囊米鳛橛言瘮?shù)的參數(shù)友元函數(shù)的參數(shù),這樣才能訪問到對象的成,這樣才能訪問到對象的成員。員。7友元函數(shù)與一般函數(shù)的不同點(diǎn)在于友元函數(shù)與一般函數(shù)的不同點(diǎn)在于:1.友元函數(shù)必須在類的定義中說明,友元函數(shù)必須在類的定義中說明,其其函數(shù)體可在類內(nèi)定義,也可在類外定函數(shù)體可在類內(nèi)定義,也可在類外定義義;2.它可以訪問該類中的所有成員(公有它可以訪問該類中的所有成員(公有的、私有的和保護(hù)的)的、私有的和保護(hù)的),而一般函數(shù),而一般函數(shù)只能訪問類中的公有成員。只能訪問類中的公有成員。8class Afl
5、oat x,y;public: A(float a, float b) x=a; y=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; cout
6、Sum(t2)endl; coutSumxy(t3)endl;成員函數(shù)成員函數(shù)友元函數(shù)友元函數(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ù)9友元函數(shù)不受類中訪問權(quán)限關(guān)鍵字的限制,可以友元函數(shù)不受類中訪問權(quán)限關(guān)鍵字的限制,可以把它放在類的私有部分,放在類的公有部分或放把它放在類的私有部分,放在類的公有部分或放在類的保護(hù)部分,其作用都是一樣的。換言之,在類的保護(hù)部分,其作用都是一樣的。換言之,在類中對友元函數(shù)指定訪問權(quán)限是
7、不起作用的在類中對友元函數(shù)指定訪問權(quán)限是不起作用的。友元函數(shù)的作用域與一般函數(shù)的作用域相同。友元函數(shù)的作用域與一般函數(shù)的作用域相同。謹(jǐn)慎使用友元函數(shù)謹(jǐn)慎使用友元函數(shù)通常使用友元函數(shù)來通常使用友元函數(shù)來取取對象中的數(shù)據(jù)成員值,而對象中的數(shù)據(jù)成員值,而不修改不修改對象中的成員值,則肯定是安全的。對象中的成員值,則肯定是安全的。10大多數(shù)情況是友元函數(shù)是某個類的成員函數(shù),大多數(shù)情況是友元函數(shù)是某個類的成員函數(shù),即即A類中的某個成員函數(shù)是類中的某個成員函數(shù)是B類中的友元函數(shù),這個成類中的友元函數(shù),這個成員函數(shù)可以直接訪問員函數(shù)可以直接訪問B類中的私有數(shù)據(jù)。類中的私有數(shù)據(jù)。這就實(shí)現(xiàn)這就實(shí)現(xiàn)了類與類之間的
8、溝通了類與類之間的溝通。注意:一個類的成員函數(shù)作為另一個類的友元函數(shù)時,注意:一個類的成員函數(shù)作為另一個類的友元函數(shù)時,應(yīng)應(yīng)先定義友元函數(shù)所在的類。先定義友元函數(shù)所在的類。class A.void fun( B &);class B.friend void fun( B &);既是類既是類A的成員函數(shù)的成員函數(shù)又是類又是類B的友元函數(shù)的友元函數(shù)11class B ;/先定義類先定義類A,則首先對類,則首先對類B作引用性說明作引用性說明class A ./類類A的成員定義的成員定義 public: void fun( B & );/函數(shù)的原型說明函數(shù)的原型說明 ;clas
9、s B. friend void A:fun( B & );/定義友元函數(shù)定義友元函數(shù); void A:fun ( B &b) /函數(shù)的完整定義函數(shù)的完整定義 ./函數(shù)體的定義函數(shù)體的定義類類A中的成員函數(shù)中的成員函數(shù)fun()是類是類B的友元函的友元函數(shù)。即在數(shù)。即在fun()中可中可以直接引用類以直接引用類B的私的私有成員。有成員。12class B;/必須在此進(jìn)行引用性說明,必須在此進(jìn)行引用性說明,class Afloat x,y;public: A(float a, float b) x=a; y=b; float Sum(B &); /說明友元函數(shù)的函數(shù)原型,
10、是類說明友元函數(shù)的函數(shù)原型,是類A的一成員函數(shù)的一成員函數(shù);class Bfloat m,n;public: B(float a,float b) m=a;n=b; friend float A:Sum(B &);/說明類說明類A的成員函數(shù)是類的成員函數(shù)是類B的友元函數(shù)的友元函數(shù)float A:Sum( B &b)/定義該友元函數(shù)定義該友元函數(shù) x=b.m+b.n; y=b.m-b.n; void main(void) A a1(3,5); B b1(10,20); a1.Sum(b1); /調(diào)用該函數(shù),調(diào)用該函數(shù),因是類因是類A的成員函數(shù),故用類的成員函數(shù),故用類A的對象調(diào)用
11、的對象調(diào)用a1.x=30a1.y=-10直接引用類直接引用類B的私有成員的私有成員類類A中有一個函數(shù)可以直中有一個函數(shù)可以直接引用類接引用類B的私有成員的私有成員13友元類友元類class A . friend class B;class B . 類類B是類是類A的友元的友元類類B可以自由使用可以自由使用類類A中的成員中的成員對于類對于類B而言,類而言,類A是透明的是透明的類類B必須通過必須通過類類A的對象的對象使用類使用類A的成員的成員14const float PI =3.1415926;class Afloat r ;float h;public: A(float a,float b)r
12、=a; h=b;float Getr()return r;float Geth()return h;friend class B;/定義類定義類B為類為類A的友元的友元;class B int number;public: B(int n=1)number=n;void Show(A &a) coutPI*a.r*a.r*a.h*numberendl; /求類求類A的某個對象的某個對象*n的體積的體積;void main(void)A a1(25,40),a2(10,40);B b1(2);b1.Show (a1); b1.Show (a2);直接引用類直接引用類A的私有成員的私有成員
13、類類B中的任何函數(shù)都中的任何函數(shù)都能使用類能使用類A中的所有中的所有私有成員。私有成員。15不管是按哪一種方式派生,基類的私有成員不管是按哪一種方式派生,基類的私有成員在派生類中都是不可見的。在派生類中都是不可見的。如果在一個派生類中要訪問基類中的私有成如果在一個派生類中要訪問基類中的私有成員,可以將這個員,可以將這個派生類聲明為基類的友元派生類聲明為基類的友元。class Base friend class Derive; .class Derive .直接使用直接使用Base中的私有成員中的私有成員16#includeclass M friend class N; /N為為M的友元,可以直
14、接使用的友元,可以直接使用M中的私有成員中的私有成員private: int i , j; void show(void)couti=itj=jt;public: M(int a=0,int b=0) i=a; j=b;class N :public M /N為為M的派生類的派生類public: N(int a=0,int b=0):M(a,b) void Print(void) show(); couti+j=i+jendl;void main(void) N n1(10,20); M m1(100,200);/ m1.show();/私有成員函數(shù),在類外不可調(diào)用私有成員函數(shù),在類外不可調(diào)用
15、 n1.Print();直接引用類直接引用類M的私有成員函數(shù)和私有成員的私有成員函數(shù)和私有成員17基類對象基類對象 M派生類對象派生類對象 Nx(私有)私有)Show( )(私有私有)x(私私有)私私有)Show( )(私私有私私有)y(公有公有)Showy( )(公有公有)showy( ) show(); coutiShow();basep-Show()基類指針基類指針派生類對象派生類對象基類對象基類對象20class Pointfloat x,y;public: Point()Point(float i,float j)x=i;y=j;float area(void) return 0.0
16、;const float Pi=3.14159;class Circle:public Point/類類Point的派生類的派生類float radius;public: Circle(float r)radius=r;float area(void) return Pi*radius*radius;void main(void) Point *pp; /基類指針,可以將派生類對象的地址賦給基類指針基類指針,可以將派生類對象的地址賦給基類指針 Circle c(5.4321); pp=&c; coutarea ()Show()Base *basep;basep=&b;basep
17、 = &d;basep -Show();即指向派生類新增的成員函數(shù)即指向派生類新增的成員函數(shù)需要將基類中的需要將基類中的Show()說明為虛函數(shù)說明為虛函數(shù)22若要訪問派生類中相同名字的函數(shù),必須將若要訪問派生類中相同名字的函數(shù),必須將基類中的基類中的同名函數(shù)定義為虛函數(shù)同名函數(shù)定義為虛函數(shù),這樣,將,這樣,將不同的派生類對象的地址賦給基類的指針變不同的派生類對象的地址賦給基類的指針變量后,就可以量后,就可以動態(tài)地根據(jù)這種賦值語句調(diào)用動態(tài)地根據(jù)這種賦值語句調(diào)用不同類中的函數(shù)不同類中的函數(shù)。23class Point float x,y;public: Point()Point(floa
18、t i,float j)x=i;y=j;virtual float area(void) return 0.0; ;const float Pi=3.14159;class Circle:public Point/類類Point的派生類的派生類float radius;public: Circle(float r)radius=r;float area(void) return Pi*radius*radius;void main(void) Point *pp; /基類指針,可以將派生類對象的地址賦給基類指針基類指針,可以將派生類對象的地址賦給基類指針 Circle c(5.4321); p
19、p=&c; coutarea ()endl; /調(diào)用虛函數(shù)調(diào)用虛函數(shù)將將area()聲明為虛函數(shù),編譯器對其進(jìn)行動態(tài)聚束,按照實(shí)際對象聲明為虛函數(shù),編譯器對其進(jìn)行動態(tài)聚束,按照實(shí)際對象c調(diào)用了調(diào)用了Circle中的函數(shù)中的函數(shù)area()。使。使Point類中的類中的area()與與Circle類中的類中的area()有一個統(tǒng)一有一個統(tǒng)一的接口。的接口。輸出:輸出:92.7011聲明為虛函數(shù)聲明為虛函數(shù)調(diào)用虛函數(shù)調(diào)用虛函數(shù)虛函數(shù)再定義虛函數(shù)再定義24虛函數(shù)的定義和使用虛函數(shù)的定義和使用 可以在程序運(yùn)行時通過調(diào)用相同的函數(shù)名而實(shí)可以在程序運(yùn)行時通過調(diào)用相同的函數(shù)名而實(shí)現(xiàn)不同功能的函數(shù)稱為
20、虛函數(shù)?,F(xiàn)不同功能的函數(shù)稱為虛函數(shù)。定義格式為:定義格式為:virtual FuncName();一旦把基類的成員函數(shù)定義為虛函數(shù),由基類所一旦把基類的成員函數(shù)定義為虛函數(shù),由基類所派生出來的所有派生類中,該函數(shù)均保持虛函數(shù)派生出來的所有派生類中,該函數(shù)均保持虛函數(shù)的特性。的特性。 在派生類中重新定義基類中的虛函數(shù)時,可以不在派生類中重新定義基類中的虛函數(shù)時,可以不用關(guān)鍵字用關(guān)鍵字virtual來修飾這個成員函數(shù)來修飾這個成員函數(shù) 。25虛函數(shù)是用關(guān)鍵字虛函數(shù)是用關(guān)鍵字virtual修飾的某基類中的修飾的某基類中的protected或或public成員函數(shù)。它可以在派生成員函數(shù)。它可以在派生類
21、中重新定義,以形成不同版本。類中重新定義,以形成不同版本。只有在程只有在程序的執(zhí)行過程中,依據(jù)指針具體指向哪個類序的執(zhí)行過程中,依據(jù)指針具體指向哪個類對象,或依據(jù)引用哪個類對象,才能確定激對象,或依據(jù)引用哪個類對象,才能確定激活哪一個版本,實(shí)現(xiàn)動態(tài)聚束活哪一個版本,實(shí)現(xiàn)動態(tài)聚束。26class Aprotected:int x;public: A()x =1000; virtual void print()cout “x=”xt;/虛函數(shù)虛函數(shù);class B:public Aint y;public: B() y=2000;void print()cout “y=”yt;/派生虛函數(shù)派生虛函
22、數(shù);class C:public Aint z;public: C()z=3000;void print()cout “z=”zprint();/調(diào)用類調(diào)用類A的虛函數(shù)的虛函數(shù) pa=&b; pa-print();/調(diào)用類調(diào)用類B的虛函數(shù)的虛函數(shù) pa=&c; pa-print();/調(diào)用類調(diào)用類C的虛函數(shù)的虛函數(shù)27class Base public : virtual int Set(int a, int b) . .;class Derive:public Basepublic : int Set(int x, int y) . .;class Base public :
23、 virtual int Set(int a, int b) . .;class Derive:public Basepublic : int Set(int x, int y=0) . .;int Set(int ,int )是虛函數(shù)是虛函數(shù)兩個兩個Set()函數(shù)參數(shù)函數(shù)參數(shù)不一致,是重載,不一致,是重載,不是虛函數(shù)不是虛函數(shù)28關(guān)于虛函數(shù),說明以下幾點(diǎn):關(guān)于虛函數(shù),說明以下幾點(diǎn):1、當(dāng)在基類中把成員函數(shù)定義為虛函數(shù)后,當(dāng)在基類中把成員函數(shù)定義為虛函數(shù)后,在其派生類中定義的虛函數(shù)必須與基類中的在其派生類中定義的虛函數(shù)必須與基類中的虛函數(shù)同名,參數(shù)的類型、順序、參數(shù)的個虛函數(shù)同名,參數(shù)的類型、
24、順序、參數(shù)的個數(shù)必須一一對應(yīng),函數(shù)的返回的類型也相同數(shù)必須一一對應(yīng),函數(shù)的返回的類型也相同。若函數(shù)名相同,但參數(shù)的個數(shù)不同或者參數(shù)若函數(shù)名相同,但參數(shù)的個數(shù)不同或者參數(shù)的類型不同時,則屬于函數(shù)的重載,而不是的類型不同時,則屬于函數(shù)的重載,而不是虛函數(shù)。若函數(shù)名不同,顯然這是不同的成虛函數(shù)。若函數(shù)名不同,顯然這是不同的成員函數(shù)。員函數(shù)。292、實(shí)現(xiàn)這種動態(tài)的多態(tài)性時,必須使用實(shí)現(xiàn)這種動態(tài)的多態(tài)性時,必須使用基類類型基類類型的指針變量的指針變量,并使該指針,并使該指針指向不同的派生類對象指向不同的派生類對象,并通過調(diào)用指針?biāo)赶虻奶摵瘮?shù)才能實(shí)現(xiàn)動態(tài)的并通過調(diào)用指針?biāo)赶虻奶摵瘮?shù)才能實(shí)現(xiàn)動態(tài)的多態(tài)性
25、。多態(tài)性。xShow()xShow()yShow()xShow()zShow()類類A類類B類類CShow()定義為虛函數(shù)定義為虛函數(shù)類類B與類與類C均為類均為類A的公有派生。的公有派生。A *p; B b;C c; p=&b ; p-Show();p=&c ; p-Show();即在程序運(yùn)行時,即在程序運(yùn)行時,通過賦值語句實(shí)通過賦值語句實(shí)現(xiàn)多態(tài)性現(xiàn)多態(tài)性303、虛函數(shù)必須是類的一個成員函數(shù),不能是虛函數(shù)必須是類的一個成員函數(shù),不能是友元函數(shù),也不能是靜態(tài)的成員函數(shù)。友元函數(shù),也不能是靜態(tài)的成員函數(shù)。4、在派生類中、在派生類中沒有重新定義虛函數(shù)沒有重新定義虛函數(shù)時,與一時,與一
26、般的成員函數(shù)一樣,當(dāng)調(diào)用這種派生類對象般的成員函數(shù)一樣,當(dāng)調(diào)用這種派生類對象的虛函數(shù)時,的虛函數(shù)時,則調(diào)用其基類中的虛函數(shù)則調(diào)用其基類中的虛函數(shù)。5、可把析構(gòu)函數(shù)定義為虛函數(shù),但是,不能可把析構(gòu)函數(shù)定義為虛函數(shù),但是,不能將構(gòu)造函數(shù)定義為虛函數(shù)將構(gòu)造函數(shù)定義為虛函數(shù)。316、虛函數(shù)與一般的成員函數(shù)相比較,、虛函數(shù)與一般的成員函數(shù)相比較,調(diào)用時的執(zhí)調(diào)用時的執(zhí)行速度要慢一些行速度要慢一些。為了實(shí)現(xiàn)多態(tài)性,在每一個派。為了實(shí)現(xiàn)多態(tài)性,在每一個派生類中均要保存相應(yīng)虛函數(shù)的入口地址表,函數(shù)生類中均要保存相應(yīng)虛函數(shù)的入口地址表,函數(shù)的調(diào)用機(jī)制也是間接實(shí)現(xiàn)的。因此,除了要編寫的調(diào)用機(jī)制也是間接實(shí)現(xiàn)的。因此,
27、除了要編寫一些通用的程序,并一定要使用虛函數(shù)才能完成一些通用的程序,并一定要使用虛函數(shù)才能完成其功能要求外,通常不必使用虛函數(shù)。其功能要求外,通常不必使用虛函數(shù)。7、一個函數(shù)如果被定義成虛函數(shù),則不管經(jīng)歷多、一個函數(shù)如果被定義成虛函數(shù),則不管經(jīng)歷多少次派生,仍將保持其虛特性,以實(shí)現(xiàn)少次派生,仍將保持其虛特性,以實(shí)現(xiàn)“一個接一個接口,多個形態(tài)口,多個形態(tài)”。32虛函數(shù)的訪問虛函數(shù)的訪問用基指針訪問與用對象名訪問用基指針訪問與用對象名訪問用基指針訪問虛函數(shù)時,指向其實(shí)際派生類用基指針訪問虛函數(shù)時,指向其實(shí)際派生類對象重新定義的函數(shù)。實(shí)現(xiàn)動態(tài)聚束。對象重新定義的函數(shù)。實(shí)現(xiàn)動態(tài)聚束。通過一個通過一個對
28、象名對象名訪問時,只能靜態(tài)聚束。即訪問時,只能靜態(tài)聚束。即由編譯器在編譯的時候決定調(diào)用哪個函數(shù)。由編譯器在編譯的時候決定調(diào)用哪個函數(shù)。33class Point float x,y;public: Point()Point(float i,float j)x=i;y=j;virtual float area(void) return 0.0; /聲明為虛函數(shù)聲明為虛函數(shù);const float Pi=3.14159;class Circle:public Point/類類Point的派生類的派生類float radius;public: Circle(float r)radius=r;floa
29、t area(void) return Pi*radius*radius;/虛函數(shù)再定義虛函數(shù)再定義;void main(void) Point *pp; /基類指針,可以將派生類對象的地址賦給基類指針基類指針,可以將派生類對象的地址賦給基類指針 Circle c(5.4321); coutc.area()endl; coutc.Point:area()endl; coutc.Circle:area ()endl;輸出:輸出:92.7011092.7011可見,利用對象名進(jìn)行調(diào)用與一般非虛函數(shù)沒有區(qū)別??梢?,利用對象名進(jìn)行調(diào)用與一般非虛函數(shù)沒有區(qū)別。用對象名調(diào)用用對象名調(diào)用area( )34c
30、lass base0public: void v(void)coutbase0n;class base1:public base0public: virtual void v(void) coutbase1n; ;class A1:public base1public: void v()coutA1n; ;class A2:public A1public: void v(void)coutA2n; ;class B1:private base1public: void v(void)coutB1n; ;class B2:public B1public: void v(void)coutv();
31、 A2 a2; (pb=&a2)-v(); B1 b1; (pb=&b1)-v(); B2 b2; (pb=&b2)-v();base0base0私有派生,在類外私有派生,在類外不能調(diào)用基類函數(shù)不能調(diào)用基類函數(shù)35class base0public: void v(void)coutbase0n;class base1:public base0public: virtual void v(void) coutbase1n; ;class A1:public base1public: void v()coutA1n; ;class A2:public A1public:
32、void v(void)coutA2n; ;class B1:private base1public: void v(void)coutB1n; ;class B2:public B1public: void v(void)coutv(); A2 a2; (pb=&a2)-v();A1A236純虛函數(shù)純虛函數(shù)在基類中不對虛函數(shù)給出有意義的實(shí)現(xiàn)在基類中不對虛函數(shù)給出有意義的實(shí)現(xiàn),它只是它只是在派生類中有具體的意義。這時基類中的虛函數(shù)在派生類中有具體的意義。這時基類中的虛函數(shù)只是一個入口,具體的目的地由不同的派生類中只是一個入口,具體的目的地由不同的派生類中的對象決定。這個虛函數(shù)稱為的對象
33、決定。這個虛函數(shù)稱為純虛函數(shù)純虛函數(shù)。class virtual ()=0;.;37class Aprotected:int x;public: A()x =1000; virtual void print()=0; /定義純虛函數(shù)定義純虛函數(shù);class B:public A /派生類派生類private: int y;public: B() y=2000;void print()cout “y=”yn;/重新定義純虛函數(shù)重新定義純虛函數(shù);class C:public A /派生類派生類int z;public: C()z=3000;void print()cout “z=”zprint()
34、; pa=&c; pa-print(); A a; pa=&a; pa-print( );y=2000z=3000抽象類抽象類不能定義抽象類的對象不能定義抽象類的對象381、在定義純虛函數(shù)時,不能定義虛函數(shù)的實(shí)、在定義純虛函數(shù)時,不能定義虛函數(shù)的實(shí)現(xiàn)部分?,F(xiàn)部分。2、把函數(shù)名賦于、把函數(shù)名賦于0,本質(zhì)上是將指向函數(shù)體,本質(zhì)上是將指向函數(shù)體的指針值賦為初值的指針值賦為初值0。與定義空函數(shù)不一樣,。與定義空函數(shù)不一樣,空函數(shù)的函數(shù)體為空,即調(diào)用該函數(shù)時,不空函數(shù)的函數(shù)體為空,即調(diào)用該函數(shù)時,不執(zhí)行任何動作。執(zhí)行任何動作。在沒有重新定義這種純虛函在沒有重新定義這種純虛函數(shù)之前,是不能
35、調(diào)用這種函數(shù)的。數(shù)之前,是不能調(diào)用這種函數(shù)的。393、把至少包含一個純虛函數(shù)的類,稱為抽象把至少包含一個純虛函數(shù)的類,稱為抽象類。這種類只能作為派生類的基類,不能用類。這種類只能作為派生類的基類,不能用來說明這種類的對象來說明這種類的對象。其理由是明顯的:因為虛函數(shù)沒有實(shí)現(xiàn)部分,其理由是明顯的:因為虛函數(shù)沒有實(shí)現(xiàn)部分,所以不能產(chǎn)生對象。但可以定義指向抽象類所以不能產(chǎn)生對象。但可以定義指向抽象類的指針,即指向這種基類的指針。當(dāng)用這種的指針,即指向這種基類的指針。當(dāng)用這種基類指針指向其派生類的對象時,基類指針指向其派生類的對象時,必須在派必須在派生類中生類中重載重載純虛函數(shù),否則會產(chǎn)生程序的運(yùn)純虛
36、函數(shù),否則會產(chǎn)生程序的運(yùn)行錯誤。行錯誤。404、在以抽象類作為基類的派生類中必須有在以抽象類作為基類的派生類中必須有純虛函數(shù)的實(shí)現(xiàn)部分,即必須有重載純虛函純虛函數(shù)的實(shí)現(xiàn)部分,即必須有重載純虛函數(shù)的函數(shù)體。否則,這樣的派生類也是不能數(shù)的函數(shù)體。否則,這樣的派生類也是不能產(chǎn)生對象的。產(chǎn)生對象的。綜上所述,可把純虛函數(shù)歸結(jié)為:綜上所述,可把純虛函數(shù)歸結(jié)為:抽象類的抽象類的唯一用途是為派生類提供基類,純虛函數(shù)的唯一用途是為派生類提供基類,純虛函數(shù)的作用是作為派生類中的成員函數(shù)的基礎(chǔ),并作用是作為派生類中的成員函數(shù)的基礎(chǔ),并實(shí)現(xiàn)動態(tài)多態(tài)性。實(shí)現(xiàn)動態(tài)多態(tài)性。41虛基類虛基類多基派生中的多條路徑具有公共基類
37、時,在這條路徑的匯合處就會多基派生中的多條路徑具有公共基類時,在這條路徑的匯合處就會因?qū)不惍a(chǎn)生多個拷貝而產(chǎn)生同名函數(shù)調(diào)用的二義性。因?qū)不惍a(chǎn)生多個拷貝而產(chǎn)生同名函數(shù)調(diào)用的二義性。解決這個問題的辦法就是把解決這個問題的辦法就是把公共基類定義為虛基類公共基類定義為虛基類,使由它派生的,使由它派生的多條路徑的匯聚處只產(chǎn)生一個拷貝。多條路徑的匯聚處只產(chǎn)生一個拷貝。class Base ;class A : public Base ;class B: public Base ;class C: public A, public B ;類類C中繼承了兩個類中繼承了兩個類Base,即有兩個類即有兩
38、個類Base的實(shí)現(xiàn)部分,的實(shí)現(xiàn)部分,在調(diào)用時產(chǎn)生了二義性。在調(diào)用時產(chǎn)生了二義性。42用虛基類進(jìn)行多重派生時,用虛基類進(jìn)行多重派生時,若虛基類沒有缺若虛基類沒有缺省的構(gòu)造函數(shù)省的構(gòu)造函數(shù),則在每一個派生類的構(gòu)造函,則在每一個派生類的構(gòu)造函數(shù)中數(shù)中都必須有對虛基類構(gòu)造函數(shù)的調(diào)用都必須有對虛基類構(gòu)造函數(shù)的調(diào)用 (且(且首先調(diào)用)。首先調(diào)用)。由虛基類派生出的對象初始化時,由虛基類派生出的對象初始化時,直接調(diào)用直接調(diào)用虛基類的構(gòu)造函數(shù)。因此,若將一個類定義虛基類的構(gòu)造函數(shù)。因此,若將一個類定義為虛基類,則一定有正確的構(gòu)造函數(shù)可供所為虛基類,則一定有正確的構(gòu)造函數(shù)可供所有派生類調(diào)用。有派生類調(diào)用。43c
39、lass basepublic:virtual void a() couta() in basen;virtual void b() coutb() in basen;virtual void c() coutc() in basen;virtual void d() coutd() in basen;virtual void e() coute() in basen;virtual void f() coutf() in basen;class A:public basepublic:virtual void a() couta() in An;virtual void b() coutb(
40、) in An;virtual void f() coutf() in An;class B:public basepublic:virtual void a() couta() in Bn;virtual void b() coutb() in Bn;virtual void c() coutc() in Bn;class C:public A,public Bpublic:virtual void a() couta() in Cn;virtual void d() couta(); pa-b(); pa-c(); pa-d(); pa-e(); pa-f();將類將類C的地址賦的地址賦值
41、時產(chǎn)生歧義值時產(chǎn)生歧義44a( )b( )c( )d( )e( )f( )a( )b( )c( )d( )e( )f( )a( )b( )f( )a( )b( )c( )d( )e( )f( )a( )c( )a( )b( )c( )d( )e( )f( )a( )b( )f( )a( )b( )c( )d( )e( )f( )a( )c( )baseABCa( )d( )AB45class basepublic:virtual void a() couta() in basen;virtual void b() coutb() in basen;virtual void c() coutc(
42、) in basen;virtual void d() coutd() in basen;virtual void e() coute() in basen;virtual void f() coutf() in basen;class A:public basepublic:virtual void a() couta() in An;virtual void b() coutb() in An;virtual void f() coutf() in An;class B:public basepublic:virtual void a() couta() in Bn;virtual voi
43、d b() coutb() in Bn;virtual void c() coutc() in Bn;class C:public A,public Bpublic:virtual void a() couta() in Cn;virtual void d() couta(); pa-b(); pa-c(); pa-d(); pa-e(); pa-f();將類將類C的地址賦的地址賦值時產(chǎn)生歧義值時產(chǎn)生歧義類類C中有兩個中有兩個base,只有一個,只有一個Aa() in Cb() in Ac() in based() in Ce() in basef() in A為避免這種情況,將為避免這種情況
44、,將base定義定義為虛基類。為虛基類。46class basepublic:virtual void a() couta() in basen;virtual void b() coutb() in basen;virtual void c() coutc() in basen;virtual void d() coutd() in basen;virtual void e() coute() in basen;virtual void f() coutf() in basen;class A:virtual public basepublic:virtual void a() couta(
45、) in An;virtual void b() coutb() in An;virtual void f() coutf() in An;class B:virtual public basepublic:virtual void a() couta() in Bn;virtual void c() coutc() in Bn;class C:public A,public Bpublic:virtual void a() couta() in Cn;virtual void d() couta(); pa-b(); pa-c(); pa-d(); pa-e(); pa-f();47a( )
46、b( )c( )d( )e( )f( )a( )b( )c( )d( )e( )f( )a( )b( )f( )a( )b( )c( )d( )e( )f( )a( )c( )a( )b( )c( )d( )e( )f( )a( )b( )f( )a( )c( )baseABCa( )d( )AB48class basepublic:virtual void a() couta() in basen;virtual void b() coutb() in basen;virtual void c() coutc() in basen;virtual void d() coutd() in ba
47、sen;virtual void e() coute() in basen;virtual void f() coutf() in basen;class A:virtual public basepublic:virtual void a() couta() in An;virtual void b() coutb() in An;virtual void f() coutf() in An;class B:virtual public basepublic:virtual void a() couta() in Bn;virtual void c() coutc() in Bn;class
48、 C:public A,public Bpublic:virtual void a() couta() in Cn;virtual void d() couta(); pa-b(); pa-c(); pa-d(); pa-e(); pa-f();類類C中只有一個中只有一個basea() in Cb() in Ac() in Bd() in Ce() in basef() in A49class basepublic:void a()couta() in basen;void b()coutb() in basen;void c()coutc() in basen;void d()coutd()
49、 in basen;void e()coute() in basen;void f()coutf() in basen;class A:virtual public basepublic:void a()couta() in An;void b()coutb() in An;void f()coutf() in An;class B:virtual public basepublic:void a()couta() in Bn;void c()coutc() in Bn;class C:public A,public Bpublic:void a()couta() in Cn;void d()
50、couta(); pa-b(); pa-c(); pa-d(); pa-e(); pa-f();類類C中只有一個中只有一個basea() in baseb() in basec() in based() in basee() in basef() in base50下面程序的輸出是下面程序的輸出是 。class Aprotected:int x;public:A()x =1000;virtual void p()cout x=xn; p2(); virtual void p2()coutA:p2()endl; ;class C:public Aint z;public:C()z=3000; v
51、oid p()cout z=zn; p2();virtual void p2()coutC:p2()p();pa=&c;pa-p();51 通常,每當(dāng)說明一個對象時,把該類中的有關(guān)成員通常,每當(dāng)說明一個對象時,把該類中的有關(guān)成員數(shù)據(jù)拷貝到該對象中,即同一類的不同對象,數(shù)據(jù)拷貝到該對象中,即同一類的不同對象,其成員數(shù)據(jù)其成員數(shù)據(jù)之間是互相獨(dú)立的之間是互相獨(dú)立的。靜態(tài)成員靜態(tài)成員 class A int x,y; public: void Setxy(int a, int b) x=a; y=b;A a1, a2;a1.xa1.ya2.xa2.y.x=a ;y=b ;.a1. Setxy(
52、)a2. Setxy()a1.Setxy(1,2);a2.Setxy(3,4);this-x=a;this-y=b;52當(dāng)我們將類的某一個當(dāng)我們將類的某一個數(shù)據(jù)成員的存儲類型指定為靜態(tài)類型數(shù)據(jù)成員的存儲類型指定為靜態(tài)類型時時,則由該類所產(chǎn)生的所有對象,其靜態(tài)成員均共享,則由該類所產(chǎn)生的所有對象,其靜態(tài)成員均共享一個一個存儲空間存儲空間,這個空間是在編譯的時候分配的這個空間是在編譯的時候分配的。換言之,在。換言之,在說明對象時,并不為靜態(tài)類型的成員分配空間。說明對象時,并不為靜態(tài)類型的成員分配空間。 在類定義中,用關(guān)鍵字在類定義中,用關(guān)鍵字static修飾的數(shù)據(jù)成員稱為靜修飾的數(shù)據(jù)成員稱為靜態(tài)數(shù)
53、據(jù)成員。態(tài)數(shù)據(jù)成員。class A int x,y; static int z; public: void Setxy(int a, int b) x=a; y=b;A a1, a2;a1.xa1.ya2.xa2.yza1. za2. z不同對象,同一空間不同對象,同一空間53有關(guān)靜態(tài)數(shù)據(jù)成員的使用,說明以下幾點(diǎn):有關(guān)靜態(tài)數(shù)據(jù)成員的使用,說明以下幾點(diǎn):1、類的靜態(tài)數(shù)據(jù)成員是、類的靜態(tài)數(shù)據(jù)成員是靜態(tài)分配存儲空間靜態(tài)分配存儲空間的,而其它成員是動態(tài)分配存儲空間的(全的,而其它成員是動態(tài)分配存儲空間的(全局變量除外)。當(dāng)類中沒有定義靜態(tài)數(shù)據(jù)成局變量除外)。當(dāng)類中沒有定義靜態(tài)數(shù)據(jù)成員時,在程序執(zhí)行期間
54、遇到說明類的對象時,員時,在程序執(zhí)行期間遇到說明類的對象時,才為對象的所有成員依次分配存儲空間,這才為對象的所有成員依次分配存儲空間,這種存儲空間的分配是動態(tài)的;種存儲空間的分配是動態(tài)的;而當(dāng)類中定義而當(dāng)類中定義了靜態(tài)數(shù)據(jù)成員時,了靜態(tài)數(shù)據(jù)成員時,在編譯時,就要為類的在編譯時,就要為類的靜態(tài)數(shù)據(jù)成員分配存儲空間靜態(tài)數(shù)據(jù)成員分配存儲空間。542、必須在文件作用域中,對靜態(tài)數(shù)據(jù)成員作必須在文件作用域中,對靜態(tài)數(shù)據(jù)成員作一次且只能作一次定義性說明一次且只能作一次定義性說明。因為靜態(tài)數(shù)。因為靜態(tài)數(shù)據(jù)成員在定義性說明時已分配了存儲空間,據(jù)成員在定義性說明時已分配了存儲空間,所以通過靜態(tài)數(shù)據(jù)成員名前加上所
55、以通過靜態(tài)數(shù)據(jù)成員名前加上類名和作用類名和作用域運(yùn)算符域運(yùn)算符,可直接引用靜態(tài)數(shù)據(jù)成員。在,可直接引用靜態(tài)數(shù)據(jù)成員。在C+中,靜態(tài)變量缺省的初值為中,靜態(tài)變量缺省的初值為0,所以靜態(tài),所以靜態(tài)數(shù)據(jù)成員總有唯一的初值。當(dāng)然,數(shù)據(jù)成員總有唯一的初值。當(dāng)然,在對靜態(tài)在對靜態(tài)數(shù)據(jù)成員作定義性的說明時,數(shù)據(jù)成員作定義性的說明時,也可以指定一也可以指定一個初值。個初值。55class Aint i,j;static int x,y;/定義靜態(tài)成員定義靜態(tài)成員public: A(int a=0,int b=0,int c=0, int d=0)i=a;j=b;x=c;y=d;void Show()cout
56、i=itj=jt; cout x=xty=yn; ;int A:x=0; /必須對靜態(tài)成員作一次定義性說明必須對靜態(tài)成員作一次定義性說明 int A:y=0; void main(void )A a(2,3,4,5);a.Show();A b(100,200,300,400);b.Show();a.Show();a.x 和和b.x在內(nèi)存中占據(jù)一個空間在內(nèi)存中占據(jù)一個空間a.y 和和b.y在內(nèi)存中占據(jù)一個空間在內(nèi)存中占據(jù)一個空間i=2j=3x=4y=5i=100 j=200 x=300 y=400i=2j=3x=300 y=40056class Aint i,j;public: static i
57、nt x;public: A(int a=0,int b=0,int c=0) i=a ; j=b ; x=c; void Show()cout i=itj=jt;cout x=xn;int A:x=500; /int A:xvoid main(void )A a(20,40,10),b(30,50,100);a.Show ();b.Show ();cout “A:x=”A:xn; /可以直接用類名引用可以直接用類名引用在類外重新定義在類外重新定義573、靜態(tài)數(shù)據(jù)成員具有全局變量和局部變量的一些、靜態(tài)數(shù)據(jù)成員具有全局變量和局部變量的一些特性。靜態(tài)數(shù)據(jù)成員與全局變量一樣都是靜態(tài)分特性。靜態(tài)數(shù)據(jù)成
58、員與全局變量一樣都是靜態(tài)分配存儲空間的,配存儲空間的,但全局變量在程序中的任何位置但全局變量在程序中的任何位置都可以訪問它,而靜態(tài)數(shù)據(jù)成員受到訪問權(quán)限的都可以訪問它,而靜態(tài)數(shù)據(jù)成員受到訪問權(quán)限的約束。約束。必須是必須是public權(quán)限時,才可能在類外進(jìn)行訪權(quán)限時,才可能在類外進(jìn)行訪問問。4、為了保持靜態(tài)數(shù)據(jù)成員取值的一致性,通常在、為了保持靜態(tài)數(shù)據(jù)成員取值的一致性,通常在構(gòu)造函數(shù)中不給靜態(tài)數(shù)據(jù)成員置初值,構(gòu)造函數(shù)中不給靜態(tài)數(shù)據(jù)成員置初值,而是在對而是在對靜態(tài)數(shù)據(jù)成員的定義性說明時指定初值靜態(tài)數(shù)據(jù)成員的定義性說明時指定初值。 58class Aint i;static int count;pub
59、lic:A(int a=0) i=a; count+; cout Number of Objects=countn; A() count-; cout Number of Objects=countn; void Show() cout i=in; cout count=countn;int A:count;void main(void )A a1(100);A b2;a1.Show();Number of Objects=1Number of Objects=2Number of Objects=3i=100count=3Number of Objects=2Number of Object
60、s=1Number of Objects=059靜態(tài)成員函數(shù)靜態(tài)成員函數(shù)可以將類的成員函數(shù)定義為靜態(tài)的成員函數(shù)。即可以將類的成員函數(shù)定義為靜態(tài)的成員函數(shù)。即使用關(guān)鍵字使用關(guān)鍵字static來修飾成員函數(shù)來修飾成員函數(shù) 。class A float x, y;public : A( ) static void sum(void) . ;60對靜態(tài)成員函數(shù)的用法說明以下幾點(diǎn):對靜態(tài)成員函數(shù)的用法說明以下幾點(diǎn):1、與靜態(tài)數(shù)據(jù)成員一樣,在類外的程序代碼中,與靜態(tài)數(shù)據(jù)成員一樣,在類外的程序代碼中,通過類名加上作用域操作符,可直接調(diào)用靜態(tài)成通過類名加上作用域操作符,可直接調(diào)用靜態(tài)成員函數(shù)員函數(shù)。 2、靜態(tài)成員函數(shù)只能直接使用本類的靜態(tài)數(shù)據(jù)成靜態(tài)成員函數(shù)只能直接使用本類的靜態(tài)數(shù)據(jù)成員或靜態(tài)成員函數(shù)員或靜態(tài)成員函數(shù),但不能直接使用非靜態(tài)的數(shù)但不能直接使用非靜態(tài)的數(shù)據(jù)成員據(jù)成員 (可以引用使用)。這是因為靜態(tài)成員函(
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 課題申報書字體標(biāo)準(zhǔn)
- 合同范本美容美發(fā)
- 傳媒影視合同范本
- 和移動合作合同范本
- 兼職寶潔勞務(wù)合同范本
- 含油銅軸承采購合同范例
- 知識產(chǎn)權(quán)保護(hù)高地建設(shè)的實(shí)踐步驟與部署
- 品牌冠名合作合同范本
- 合作投資入股合同范本
- 加快建設(shè)知識產(chǎn)權(quán)保護(hù)高地的戰(zhàn)略規(guī)劃
- 山西眾輝電力服務(wù)公司歷年真題
- 修建蓄水池施工合同協(xié)議書范本
- CJJ-181-2012(精華部分)城鎮(zhèn)排水管道檢測與評估技術(shù)規(guī)程
- 《乳腺癌的防治》課件
- 個人所得稅個人所得稅
- 《小貓的九個命》
- 大班健康《愛是什么》課件
- 特種作業(yè)(鍋爐工)安全培訓(xùn)
- 煤礦違章行為及預(yù)防
- 零信任網(wǎng)絡(luò)安全模型:原理與實(shí)踐
- 《哲學(xué)概論(第2版)》-課件 第2、3章 哲學(xué)的特性、方法;哲學(xué)的價值
評論
0/150
提交評論