C++面向?qū)ο蟪绦蛟O計3_第1頁
C++面向?qū)ο蟪绦蛟O計3_第2頁
C++面向?qū)ο蟪绦蛟O計3_第3頁
C++面向?qū)ο蟪绦蛟O計3_第4頁
C++面向?qū)ο蟪绦蛟O計3_第5頁
已閱讀5頁,還剩85頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、第三章 關于類和對象的進一步討論1構造函數(shù)和析構函數(shù)是在類體中說明的兩種特殊的成員函數(shù)。構造函數(shù)是在創(chuàng)建對象時,使用給定的值來將對象初始化。析構函數(shù)的功能正好相反,是在系統(tǒng)釋放對象前,對對象做一些善后工作。2構造函數(shù)是類的成員函數(shù),系統(tǒng)約定構造函數(shù)名必須與類名相同。構造函數(shù)提供了初始化對象的一種簡單的方法。構造函數(shù)可以帶參數(shù)、可以重載,同時沒有返回值。3class Afloat x,y;public:A(float a,float b) x=a; y=b;/構造函數(shù),初始化對象float Sum(void) return x+y; void Set(float a,float b) x=a;y

2、=b;Print(void) coutx=xty=yendl;void main(void)A a1(2.0, 3.0);/定義時調(diào)用構造函數(shù)初始化A a2(1.0,2.0);a2.Set(10.0, 20.0); /利用成員函數(shù)重新為對象賦值 a1.Print();a2.Print();4對構造函數(shù),說明以下幾點:1.構造函數(shù)的函數(shù)名必須與類名相同。構造函數(shù)的主要作用是完成初始化對象的數(shù)據(jù)成員以及其它的初始化工作。2. 在定義構造函數(shù)時,不能指定函數(shù)返回值的類型,也不能指定為void類型。3. 一個類可以定義若干個構造函數(shù)。當定義多個構造函數(shù)時,必須滿足函數(shù)重載的原則。54.構造函數(shù)可以指定

3、參數(shù)的缺省值。5.若定義的類要說明該類的對象時,構造函數(shù)必須是公有的成員函數(shù)。如果定義的類僅用于派生其它類時,則可將構造函數(shù)定義為保護的成員函數(shù)。由于構造函數(shù)屬于類的成員函數(shù),它對私有數(shù)據(jù)成員、保護的數(shù)據(jù)成員和公有的數(shù)據(jù)成員均能進行初始化。6class Afloat x,y;public:A(float a, float b=10) x=a; y=b; A() x=0; y=0; void Print(void) coutxtyendl; ;void main(void) A a1, a2(20.0), a3(3.0, 7.0); a1.Print(); a2.Print(); a3.Prin

4、t(); 00201037帶缺省參數(shù)的構造函數(shù)不帶參數(shù)的構造函數(shù)每一個對象必須要有相應的構造函數(shù)7每一個對象必須要有相應的構造函數(shù)若沒有顯式定義構造函數(shù),系統(tǒng)默認缺省的構造函數(shù)。class Afloat x,y;public:A() void Print(void) coutxtyendl; ;隱含的缺省的構造函數(shù)A a1, a2;只允許這樣定義對象對象開辟了空間,但沒有初始化8對局部對象,靜態(tài)對象,全局對象的初始化對于局部對象,每次定義對象時,都要調(diào)用構造函數(shù)。對于靜態(tài)對象,是在首次定義對象時,調(diào)用構造函數(shù)的,且由于對象一直存在,只調(diào)用一次構造函數(shù)。對于全局對象,是在main函數(shù)執(zhí)行之前調(diào)用

5、構造函數(shù)的。9class A int x,y; public: A(int a) x=a; cout“1n”; A(int a, int b) x=a,y=b;cout“2n”;A a1(3);void f(void) A b(2,3);void main(void) A a2(4,5); f(); f();122210class Afloat x,y;public: A(float a, float b)x=a;y=b;cout初始化自動局部對象n; A()x=0; y=0; cout初始化靜態(tài)局部對象n; A(float a)x=a; y=0; cout初始化全局對象n; void Pri

6、nt(void) coutxtyendl; ;A a0(100.0);/定義全局對象void f(void) cout 進入f()函數(shù)n;A a2(1,2); static A a3; /初始化局部靜態(tài)對象 void main(void) cout進入main函數(shù)n; A a1(3.0, 7.0);/定義局部自動對象 f(); f(); 初始化全局對象進入main函數(shù)初始化自動局部對象進入f()函數(shù)初始化局部靜態(tài)變量進入f()函數(shù)初始化自動局部對象初始化自動局部對象11缺省的構造函數(shù) 在定義類時,若沒有定義類的構造函數(shù),則編譯器自動產(chǎn)生一個缺省的構造函數(shù),其格式為:className:clas

7、sName() 缺省的構造函數(shù)并不對所產(chǎn)生對象的數(shù)據(jù)成員賦初值;即新產(chǎn)生對象的數(shù)據(jù)成員的值是不確定的。 12class Afloat x,y;public:A()/缺省的構造函數(shù),編譯器自動產(chǎn)生,可以不寫float Sum(void) return x+y; void Set(float a,float b) x=a;y=b; void Print(void) coutx=xty=yendl; ;void main(void)A a1,a2;/產(chǎn)生對象時,自動調(diào)用缺省的構造函數(shù),不賦值a1.Set (2.0,4.0);couta1: ; a1.Print ();couta1.sum=a1.Su

8、m ()endl;a2.Print();/打印隨機值13關于缺省的構造函數(shù),說明以下幾點:1、在定義類時,只要顯式定義了一個類的構造函數(shù),則編譯器就不產(chǎn)生缺省的構造函數(shù)2、所有的對象在定義時,必須調(diào)用構造函數(shù)不存在沒有構造函數(shù)的對象!14class Afloat x,y;public: A(float a,float b)x=a;y=b; void Print(void)coutxtyendl;void main(void)A a1;A a2(3.0,30.0);顯式定義了構造函數(shù),不產(chǎn)生缺省的構造函數(shù)error,定義時,沒有構造函數(shù)可供調(diào)用153、在類中,若定義了沒有參數(shù)的構造函數(shù),或各參數(shù)

9、均有缺省值的構造函數(shù)也稱為缺省的構造函數(shù),缺省的構造函數(shù)只能有一個。4、產(chǎn)生對象時,系統(tǒng)必定要調(diào)用構造函數(shù)。所以任一對象的構造函數(shù)必須唯一。16class Afloat x,y;public: A(float a=10,float b=20)x=a;y=b; A() void Print(void)coutxtyn;float scoren5; 錯誤!數(shù)組的維數(shù)必須是常量利用 new 運算符可以在程序中動態(tài)開辟內(nèi)存空間。new 數(shù)據(jù)類型單位數(shù);new int4;在內(nèi)存中開辟了4個int型的數(shù)據(jù)空間,即16個字節(jié)C+的new與delete運算符 18new 相當于一個函數(shù),在內(nèi)存開辟完空間后,返

10、回這個空間的首地址,這時,這個地址必須用一個指針保存下來,才不會丟失。int *p;pp=new int;new開辟的空間*p=6;6可以用*p對這個空間進行運算。new int;在內(nèi)存中開辟出四個字節(jié)的空間19int n,* p;cinn;p=new intn;p指向新開辟空間的首地址。p同樣,利用new運算符也可以開辟連續(xù)的多個空間(數(shù)組)。for(int i=0;ipi;可以用pi的形式來引用新開辟的內(nèi)存單元。20注意:用new開辟的內(nèi)存單元沒有名字,指向其首地址的指針是引用其的唯一途徑,若指針變量重新賦值,則用new開辟的內(nèi)存單元就在內(nèi)存中“丟失”了,別的程序也不能占用這段單元,直到重

11、新開機為止。int * p, a4;p=new int4;p=a;anew開辟的單元p該段內(nèi)存由于失去了“名字”,再也無法引用21用 new 運算符分配的空間,不能在分配空間時進行初始化。 delete運算符用來將動態(tài)分配到的內(nèi)存空間歸還給系統(tǒng),使用格式為: delete p;同樣,用new開辟的內(nèi)存單元如果程序不“主動”收回,那么這段空間就一直存在,直到重新開機為止。22delete也可以收回用new開辟的連續(xù)的空間。int *point;cinn;point=new intn;.delete point;int *point;point=new int;.delete point;注意:在

12、此期間,point指針不能重新賦值,只有用new開辟的空間才能用delete收回。當內(nèi)存中沒有足夠的空間給予分配時,new 運算符返回空指針NULL(0)。23構造函數(shù)與new運算符 可以使用new運算符來動態(tài)地建立對象。建立時要自動調(diào)用構造函數(shù),以便完成初始化對象的數(shù)據(jù)成員。最后返回這個動態(tài)對象的起始地址。用new運算符產(chǎn)生的動態(tài)對象,在不再使用這種對象時,必須用delete運算符來釋放對象所占用的存儲空間。 用new建立類的對象時,可以使用參數(shù)初始化動態(tài)空間。 24class Afloat x,y;public:A(float a, float b)x=a;y=b;A()x=0; y=0;

13、void Print(void) coutxtyPrint(); pa2-Print(); delete pa1; /用delete釋放空間 delete pa2; /用delete釋放空間50025析構函數(shù) 析構函數(shù)的作用與構造函數(shù)正好相反,是在對象的生命期結束時,釋放系統(tǒng)為對象所分配的空間,即要撤消一個對象。析構函數(shù)也是類的成員函數(shù),定義析構函數(shù)的格式為:ClassName:ClassName( ) ./ 函數(shù)體; 26析構 函數(shù)的特點如下:1、析構函數(shù)是成員函數(shù),函數(shù)體可寫在類體內(nèi),也可寫在類體外。2、析構函數(shù)是一個特殊的成員函數(shù),函數(shù)名必須與類名相同,并在其前面加上字符“”,以便和構造

14、函數(shù)名相區(qū)別。3、析構函數(shù)不能帶有任何參數(shù),不能有返回值,不指定函數(shù)類型。27在程序的執(zhí)行過程中,當遇到某一對象的生存期結束時,系統(tǒng)自動調(diào)用析構函數(shù),然后再收回為對象分配的存儲空間。4、一個類中,只能定義一個析構函數(shù),析構函數(shù)不允許重載。5、析構函數(shù)是在撤消對象時由系統(tǒng)自動調(diào)用的。28class Afloat x,y;public: A(float a,float b) x=a;y=b;cout調(diào)用非缺省的構造函數(shù)n; A() x=0; y=0; cout調(diào)用缺省的構造函數(shù)n ; A() cout調(diào)用析構函數(shù)n; void Print(void) coutxtyendl;void main(v

15、oid)A a1; A a2(3.0,30.0);cout退出主函數(shù)n;調(diào)用缺省的構造函數(shù)調(diào)用非缺省的構造函數(shù)退出主函數(shù)調(diào)用析構函數(shù)調(diào)用析構函數(shù)29 在程序的執(zhí)行過程中,對象如果用new運算符開辟了空間,則在類中應該定義一個析構函數(shù),并在析構函數(shù)中使用delete刪除由new分配的內(nèi)存空間。因為在撤消對象時,系統(tǒng)自動收回為對象所分配的存儲空間,而不能自動收回由new分配的動態(tài)存儲空間。30class Strchar *Sp; int Length;public:Str(char *string) if(string)Length=strlen(string); Sp=new charLengt

16、h+1;strcpy(Sp,string); else Sp=0;void Show(void)coutSpendl;Str() if(Sp)delete Sp;void main(void)Str s1(Study C+);s1.Show();在構造函數(shù)中將成員數(shù)據(jù)指針指向動態(tài)開辟的內(nèi)存用初值為開辟的內(nèi)存賦值析構函數(shù),當釋放對象時收回用new開辟的空間31Study C+0stringLength=strlen(string);Sp=new charLength+1;Spnew開辟的空間strcpy(Sp,string);Study C+032用new運算符為對象分配動態(tài)存儲空間時,調(diào)用了構

17、造函數(shù),用delete刪除這個空間時,調(diào)用了析構函數(shù)。當使用運算符delete刪除一個由new動態(tài)產(chǎn)生的對象時,它首先調(diào)用該對象的析構函數(shù),然后再釋放這個對象占用的內(nèi)存空間??梢杂胣ew運算符為對象分配存儲空間,如:A *p;p=new A;這時必須用delete才能釋放這一空間。delete p;33class Afloat x,y;public: A(float a, float b)x=a;y=b;cout調(diào)用了構造函數(shù)n; void Print(void) coutxtyendl; A() cout調(diào)用了析構函數(shù)n; ;void main(void) coutPrint(); dele

18、te pa1; /調(diào)用析構函數(shù) cout退出main()函數(shù)n;進入main()函數(shù)調(diào)用了構造函數(shù)35調(diào)用了析構函數(shù)退出main()函數(shù)34不同存儲類型的對象調(diào)用構造函數(shù)及析構函數(shù) 1、對于全局定義的對象(在函數(shù)外定義的對象),在程序開始執(zhí)行時,調(diào)用構造函數(shù);到程序結束時,調(diào)用析構函數(shù)。2、對于局部定義的對象(在函數(shù)內(nèi)定義的對象),當程序執(zhí)行到定義對象的地方時,調(diào)用構造函數(shù);在退出對象的作用域時,調(diào)用析構函數(shù)。3、用static定義的局部對象,在首次到達對象的定義時調(diào)用構造函數(shù);到程序結束時,調(diào)用析構函數(shù)35 4、對于用new運算符動態(tài)生成的對象,在產(chǎn)生對象時調(diào)用構造函數(shù),只有使用delete

19、運算符來釋放對象時,才調(diào)用析構函數(shù)。若不使用delete來撤消動態(tài)生成的對象,程序結束時,對象仍存在,并占用相應的存儲空間,即系統(tǒng)不能自動地調(diào)用析構函數(shù)來撤消動態(tài)生成的對象。36class Afloat x,y;public: A(float a, float b)x=a;y=b;cout初始化自動局部對象n; A()x=0; y=0; cout初始化靜態(tài)局部對象n; A(float a)x=a; y=0; cout初始化全局對象n; A() cout“調(diào)用析構函數(shù)”endl; ;A a0(100.0);/定義全局對象void f(void) cout 進入f()函數(shù)n; A ab(10.0,

20、 20.0);/定義局部自動對象 static A a3; /初始化局部靜態(tài)對象 void main(void) cout進入main函數(shù)n;f(); f(); 初始化全局對象進入main函數(shù)初始化自動局部對象進入f()函數(shù)初始化靜態(tài)局部對象進入f()函數(shù)初始化自動局部對象調(diào)用析構函數(shù)調(diào)用析構函數(shù)調(diào)用析構函數(shù)調(diào)用析構函數(shù)37動態(tài)構造及析構對象數(shù)組 用new運算符來動態(tài)生成對象數(shù)組時,自動調(diào)用構造函數(shù),而用delete運算符來釋放p1所指向的對象數(shù)組占用的存儲空間時,在指針變量的前面必須加上 , 才能將數(shù)組元素所占用的空間全部釋放。否則,只釋放第0個元素所占用的空間。pa1=new A3;. d

21、elete pa1; 38class Afloat x,y;public: A(float a=0, float b=0)x=a; y=b;cout調(diào)用了構造函數(shù)n; void Print(void) coutxtyendl; A() cout調(diào)用了析構函數(shù)n; ;void main(void) cout進入main()函數(shù)n; A *pa1; pa1=new A3;/開辟數(shù)組空間coutn完成開辟數(shù)組空間nn; delete pa1; /必須用刪除開辟的空間 cout退出main()函數(shù)n;進入main()函數(shù)調(diào)用了構造函數(shù)調(diào)用了構造函數(shù)調(diào)用了構造函數(shù)完成開辟數(shù)組空間調(diào)用了析構函數(shù)調(diào)用了析構

22、函數(shù)調(diào)用了析構函數(shù)退出main()函數(shù)39缺省的析構函數(shù)若在類的定義中沒有顯式地定義析構函數(shù)時,則編譯器自動地產(chǎn)生一個缺省的析構函數(shù),其格式為:ClassName:ClassName() ;任何對象都必須有構造函數(shù)和析構函數(shù),但在撤消對象時,要釋放對象的數(shù)據(jù)成員用new運算符分配的動態(tài)空間時,必須顯式地定義析構函數(shù)。 40實現(xiàn)類型轉換的構造函數(shù)同類型的對象可以相互賦值,相當于類中的數(shù)據(jù)成員相互賦值;如果直接將數(shù)據(jù)賦給對象,所賦入的數(shù)據(jù)需要強制類型轉換,這種轉換需要調(diào)用構造函數(shù)。41class Afloat x,y;public: A(float a,float b) x=a;y=b;cout調(diào)

23、用構造函數(shù)n; A() cout調(diào)用析構函數(shù)n; void Print(void) coutxtyendl;void main(void) A a1(1.0, 10.0); a1.Print(); a1=A(3.0 , 30.0); a1.Print(); cout退出主函數(shù)n;調(diào)用構造函數(shù)產(chǎn)生臨時對象,初始化并賦值后立即釋放1 10調(diào)用構造函數(shù)調(diào)用析構函數(shù)330退出主函數(shù)調(diào)用析構函數(shù)42注意:當構造函數(shù)只有一個參數(shù)時,可以用= 強制賦值。class Bfloat x;public: B(float a) x=a; cout調(diào)用構造函數(shù)n; B() cout調(diào)用析構函數(shù)n; void Prin

24、t(void) coutxendl; ;void main(void)B b1(1.0) ;b1.Print(); B b2=100; b2.Print(); b1=10; b1.Print(); coutx=a;this-y=b;系統(tǒng)自動將對象的指針帶到成員函數(shù)中44當對一個對象調(diào)用成員函數(shù)時,編譯程序先將對象的地址賦給this指針,然后調(diào)用成員函數(shù),每次成員函數(shù)存取數(shù)據(jù)成員時,也隱含使用this指針。this指針具有如下形式的缺省說明: Stu *const this; 類名即 this 指針里的地址是一個常量45class Spublic : char *strp; int length

25、; void Ini(char *s); void Print(void); void Copy(S &s);void main(void)S s1,s2;s1.Ini(“China”); s2.Ini(“”);s1.Print(); s2.Copy(s1); s2.Print(); s1.Copy(s1);void S:Ini(char *s) length=strlen(s); strp=new charlength+1; strcpy(strp, s);void S:Print(void) coutstrpendl; void S:Copy(S &s) if(strp) delete s

26、trp; length= s.length; strp=new charlength+1; strcpy(strp, s.strp); 46void S:Ini(char *s) length=strlen(s); strp=new charlength+1; strcpy(strp, s);void S:Copy(S &s) if(strp) delete strp; length= s.length; strp=new charlength+1; strcpy(strp, s.strp); *strplengthIni( )Print( )Copy( )S字符串首址字符串長度s1.Ini(

27、“China”);求長度對象動態(tài)開辟空間空間賦值length=5strpChina0s2.Copy(s1);0strpChina047void S:Copy(S &s) if(strp) delete strp; length= s.length; strp=new charlength+1; strcpy(strp, s.strp); s1.Copy(s1);strpChina0length=5隨機隨機隨機隨機隨機隨機失去了原來的內(nèi)容,不能正確復制48void S:Copy(S &s) if(&s=this) cout“不能復制本身n”; else if(strp) delete strp;

28、 length= s.length; strp=new charlength+1; strcpy(strp, s.strp); 判斷是否是自身復制this為正在調(diào)用該函數(shù)的對象的地址s2.Copy(s1);s1.Copy(s1);if(s=*this)49完成拷貝功能的構造函數(shù) 可以在定義一個對象的時候用另一個對象為其初始化,即構造函數(shù)的參數(shù)是另一個對象的引用,這種構造函數(shù)常為完成拷貝功能的構造函數(shù)。完成拷貝功能的構造函數(shù)的一般格式為:ClassName:ClassName(ClassName &)./ 函數(shù)體完成對應數(shù)據(jù)成員的賦值50class Afloat x,y;public: A(fl

29、oat a=0, float b=0)x=a; y=b; A(A &a) x=a.x; y=a.y;;void main(void) A a1(1.0,2.0); A a2(a1);形參必須是同類型對象的引用實參是同類型的對象51class Afloat x,y;public: A(float a=0, float b=0)x=a; y=b;cout調(diào)用了構造函數(shù)n; A(A &a) x=a.x;y=a.y;cout“調(diào)用了完成拷貝功能的構造函數(shù)n”; void Print(void) coutxtyendl; A() cout調(diào)用了析構函數(shù)n; ;void main(void) A a1(1

30、.0,2.0); A a2(a1); a1.Print(); a2.Print();調(diào)用了構造函數(shù)調(diào)用了完成拷貝功能的構造函數(shù)1212調(diào)用了析構函數(shù)調(diào)用了析構函數(shù)用已有的對象中的數(shù)據(jù)為新創(chuàng)建的對象賦值52如果沒有定義完成拷貝功能的構造函數(shù),編譯器自動生成一個隱含的完成拷貝功能的構造函數(shù),依次完成類中對應數(shù)據(jù)成員的拷貝。 A:A(A &a) x=a.x; y=a.y; 隱含的構造函數(shù)53class Afloat x,y;public: A(float a=0, float b=0)x=a; y=b;cout調(diào)用了構造函數(shù)n; void Print(void) coutxtyendl; A() c

31、out調(diào)用了析構函數(shù)n; ;void main(void) A a1(1.0,2.0); A a2(a1); A a3=a1;/可以這樣賦值 a1.Print(); a2.Print(); a3.Print();調(diào)用了構造函數(shù)121212調(diào)用了析構函數(shù)調(diào)用了析構函數(shù)調(diào)用了析構函數(shù)隱含了拷貝的構造函數(shù)54由編譯器為每個類產(chǎn)生的這種隱含的完成拷貝功能的構造函數(shù),依次完成類中對應數(shù)據(jù)成員的拷貝。但是,當類中的數(shù)據(jù)成員中使用new運算符,動態(tài)地申請存儲空間進行賦初值時,必須在類中顯式地定義一個完成拷貝功能的構造函數(shù),以便正確實現(xiàn)數(shù)據(jù)成員的復制。55class Str int Length; char

32、*Sp;public: Str(char *string) if(string)Length=strlen(string); Sp=new charLength+1; strcpy(Sp,string); else Sp=0; void Show(void)coutSpendl;Str()if(Sp) delete Sp;void main(void)Str s1(Study C+);Str s2(s1);s1.Show ();s2.Show ();隱含的拷貝構造函數(shù)為:Str:Str(Str &s)Length=s.Length;Sp=s.Sp;“Study C+”s1.Sps2.Spnew

33、開辟的空間同一空間釋放兩次,造成運行錯誤。56在這種情況下,必須要定義完成拷貝功能的構造函數(shù)。Str:Str(Str &s) if(s.Sp)Length=s.Length ;Sp=new charLength+1;strcpy(Sp,s.Sp);else Sp=0; Str s2(s1);“Study C+”s1.Sp原來s1開辟的空間“Study C+”s2.Sp拷貝函數(shù)中用new開辟的空間57構造函數(shù)與對象成員對類A的對象初始化的同時還要對其成員數(shù)據(jù)類B的對象進行初始化,所以,類A的構造函數(shù)中要調(diào)用類B的構造函數(shù)。class B .;class A int x , y; B b1,b2;

34、 ;在類A中包含類B的對象58class A float x,y;public: A(int a,int b)x=a;y=b; void Show() cout x=xty=yn; ;class Cfloat z; A a1;/類C的數(shù)據(jù)成員為類A 的對象a1public: C(int a,int b,int c):a1(b, c) z=a;/類C的對象初始化 void Show()cout “z=an;a1.Show(); ;void main(void)C c1(1, 2, 3 );/對類C的對象初始化c1.Show();在類C中調(diào)用類A的成員函數(shù)利用類A的構造函數(shù)對類A的對象初始化59x

35、yA()Show()za1.xa1.ya1.A()a1.Show()C( )Show( )a1ACa1(b, c)60class A float x,y;public: A(int a,int b)x=a;y=b;void Show() cout x=xty=yn; ;class Bfloat x1,y1;public:B(int a, int b) x1=a; y1=b; void Show() cout“x1=“x1t“y=“yn;class Cfloat z; A a1; B b1;public: C(int a,int b,int c,int d, int e):a1(a+b, c)

36、,b1(a,d) z=e; void Show()cout “z=an;a1.Show();b1.Show(); ;void main(void)C c1(1, 2, 3 ,4,5);/對類C的對象初始化 對象初始化的參數(shù)可以是表達式61對對象成員的構造函數(shù)的調(diào)用順序取決于這些對象成員在類中說明的順序,與它們在成員初始化列表中的順序無關。當建立類ClassName的對象時,先調(diào)用各個對象成員的構造函數(shù),初始化相應的對象成員,然后才執(zhí)行類ClassName的構造函數(shù),初始化類ClassName中的其它成員。析構函數(shù)的調(diào)用順序與構造函數(shù)正好相反。62class Afloat x;public: A

37、(int a) x=a; cout“調(diào)用了A的構造函數(shù)n”; A()cout“調(diào)用了A的析構函數(shù)n”;class Bfloat y;public: B(int a) y=a; cout“調(diào)用了B的構造函數(shù)n”; B()cout“調(diào)用了B的析構函數(shù)n”;class Cfloat z; B b1; A a1;public: C(int a,int b,int c): a1(a),b1(b)z=c;cout“調(diào)用了C的構造函數(shù)n”; C()coutx=a;this-y=b;64當我們將類的某一個數(shù)據(jù)成員的存儲類型指定為靜態(tài)類型時,則由該類所產(chǎn)生的所有對象,其靜態(tài)成員均共享一個存儲空間,這個空間是在編

38、譯的時候分配的。換言之,在說明對象時,并不為靜態(tài)類型的成員分配空間。 在類定義中,用關鍵字static修飾的數(shù)據(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不同對象,同一空間65有關靜態(tài)數(shù)據(jù)成員的使用,說明以下幾點:1、類的靜態(tài)數(shù)據(jù)成員是靜態(tài)分配存儲空間的,而其它成員是動態(tài)分配存儲空間的(全局變量除外)。當類中沒有定義靜態(tài)數(shù)據(jù)成員時,在程序執(zhí)行期間遇到說明類的對象時,才為對象的所有成員依次分配存儲空間

39、,這種存儲空間的分配是動態(tài)的;而當類中定義了靜態(tài)數(shù)據(jù)成員時,在編譯時,就要為類的靜態(tài)數(shù)據(jù)成員分配存儲空間。662、必須在文件作用域中,對靜態(tài)數(shù)據(jù)成員作一次且只能作一次定義性說明。因為靜態(tài)數(shù)據(jù)成員在定義性說明時已分配了存儲空間,所以通過靜態(tài)數(shù)據(jù)成員名前加上類名和作用域運算符,可直接引用靜態(tài)數(shù)據(jù)成員。在C+中,靜態(tài)變量缺省的初值為0,所以靜態(tài)數(shù)據(jù)成員總有唯一的初值。當然,在對靜態(tài)數(shù)據(jù)成員作定義性的說明時,也可以指定一個初值。67class Aint i,j;static int x,y;/定義靜態(tài)成員public:A(int a=0,int b=0,int c=0, int d=0)i=a;j=b

40、;x=c;y=d;void Show()cout i=itj=jt; cout x=xty=yn; ;int A:x=0; /必須對靜態(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ù)一個空間a.y 和b.y在內(nèi)存中占據(jù)一個空間i=2j=3x=4y=5i=100j=200 x=300y=400i=2j=3x=300y=40068class Aint i,j;public: static int x;public: A(

41、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; /可以直接用類名引用在類外重新定義693、靜態(tài)數(shù)據(jù)成員具有全局變量和局部變量的一些特性。靜態(tài)數(shù)據(jù)成員與全局變量一樣都是靜態(tài)分配存儲空間的,但全局變量在程序中的任何位置都可以訪問它,而靜態(tài)數(shù)據(jù)成員受到訪問權限的約束。必須是public權限時,才可能

42、在類外進行訪問。4、為了保持靜態(tài)數(shù)據(jù)成員取值的一致性,通常在構造函數(shù)中不給靜態(tài)數(shù)據(jù)成員置初值,而是在對靜態(tài)數(shù)據(jù)成員的定義性說明時指定初值。 70class Aint i;static int count;public: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 b(2);a1.Show(

43、);Number of Objects=1Number of Objects=2i=100count=2Number of Objects=1Number of Objects=071靜態(tài)成員函數(shù)可以將類的成員函數(shù)定義為靜態(tài)的成員函數(shù)。即使用關鍵字static來修飾成員函數(shù) 。class A float x, y;public : A( ) static void sum(void) . ;72對靜態(tài)成員函數(shù)的用法說明以下幾點:1、與靜態(tài)數(shù)據(jù)成員一樣,在類外的程序代碼中,通過類名加上作用域操作符,可直接調(diào)用靜態(tài)成員函數(shù)。 2、靜態(tài)成員函數(shù)只能直接使用本類的靜態(tài)數(shù)據(jù)成員或靜態(tài)成員函數(shù),但不能直接

44、使用非靜態(tài)的數(shù)據(jù)成員 (可以引用使用)。這是因為靜態(tài)成員函數(shù)可被其它程序代碼直接調(diào)用,所以,它不包含對象地址的this指針。 73class Tc private:int A;static int B;/靜態(tài)數(shù)據(jù)成員public:Tc(int a)A=a; B+=a;static void display(Tc c)/Tc的對象為形參 coutA=c.A,B=Bendl;int Tc:B=2;void main(void)Tc a(2),b(4);Tc:display (a);Tc:display (b);非靜態(tài)成員,用對象名來引用靜態(tài)成員,直接引用直接用類名來調(diào)用靜態(tài)成員函數(shù)A=2,B=8A

45、=4,B=8743、靜態(tài)成員函數(shù)的實現(xiàn)部分在類定義之外定義時,其前面不能加修飾詞static。這是由于關鍵字static不是數(shù)據(jù)類型的組成部分,因此,在類外定義靜態(tài)成員函數(shù)的實現(xiàn)部分時,不能使用這個關鍵字4、不能把靜態(tài)成員函數(shù)定義為虛函數(shù)。靜態(tài)成員函數(shù)也是在編譯時分配存儲空間,所以在程序的執(zhí)行過程中不能提供多態(tài)性。5、可將靜態(tài)成員函數(shù)定義為內(nèi)聯(lián)的(inline),其定義方法與非靜態(tài)成員函數(shù)完全相同。75class Tc private:int A;static int B;/靜態(tài)數(shù)據(jù)成員public:Tc(int a)A=a; B+=a;static void display(Tc c);/T

46、c的對象為形參;void Tc:display(Tc c)/不用static修飾 coutA=c.A,B=Bendl;int Tc:B=2;void main(void)Tc a(2),b(4);Tc:display (a);Tc:display (b);函數(shù)原型類外定義76思考: 下述程序的輸出結果是_。 #includeclass Samplepublic:Sample() coutConstructorendl;Sample()coutDestructorendl;void fun(int i)static Sample c;couti=iendl;void main(void)fun(

47、10);fun(20);77友元函數(shù)類中私有和保護的成員在類外不能被訪問。友元函數(shù)是一種定義在類外部的普通函數(shù),其特點是能夠訪問類中私有成員和保護成員,即類的訪問權限的限制對其不起作用。友元78友元函數(shù)需要在類體內(nèi)進行說明,在前面加上關鍵字friend。一般格式為:friend FuncName();friend float Volume(A &a);關鍵字返回值類型函數(shù)名函數(shù)參數(shù)79友元函數(shù)不是成員函數(shù),用法也與普通的函數(shù)完全一致,只不過它能訪問類中所有的數(shù)據(jù)。友元函數(shù)破壞了類的封裝性和隱蔽性,使得非成員函數(shù)可以訪問類的私有成員。一個類的友元可以自由地用該類中的所有成員。80class Af

48、loat 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 main(void) A t1(4,5),t2(10,20); coutt1.Sum()endl; coutSum(t2)endl;友元函數(shù)成員函數(shù)友元函數(shù)的調(diào)用,直接調(diào)用成員函數(shù)的調(diào)用,利用對象名調(diào)用友元函數(shù)只能用對象名引用類中的數(shù)據(jù)。私有數(shù)據(jù)81有關友元函數(shù)的使用,說明如下:友元函數(shù)不是類的成員函數(shù)友元函數(shù)近似于普通的函數(shù),它不帶有this指針,因此必須將對象名或?qū)ο蟮囊米鳛橛言瘮?shù)的參數(shù),這樣才能訪問到對象的成員。82友元函數(shù)與一般函數(shù)的不同點在于:友元函數(shù)必須在類的定義中說明,其函數(shù)體可在類內(nèi)定義,也可在類外定義;它可以訪問該類中的所有成員(公有的、私有的和保護的),而一般函數(shù)只能訪問類中的公有成員。83class Afloat 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 &); ;floa

溫馨提示

  • 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

提交評論