




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、第第9章章 關于類和對象的進一步討論關于類和對象的進一步討論9.1 構造函數構造函數9.2 析構函數析構函數9.3 調用構造函數和析構函數的順序調用構造函數和析構函數的順序9.4 對象數組對象數組9.5 對象指針對象指針9.6 對象的動態建立和釋放對象的動態建立和釋放9.7 對象的賦值和復制對象的賦值和復制9.8 靜態成員靜態成員9.9 友元友元9.1 構造函數構造函數l在建立一個對象時,常常需要作某些初始化在建立一個對象時,常常需要作某些初始化的工作,例如對數據成員賦初值。如果一個的工作,例如對數據成員賦初值。如果一個數據成員未被賦值,則它的值是不可預知的,數據成員未被賦值,則它的值是不可預
2、知的,因為在系統為它分配內存時,保留了這些存因為在系統為它分配內存時,保留了這些存儲單元的原狀,這就成為了這些數據成員的儲單元的原狀,這就成為了這些數據成員的初始值。這種狀況顯然是與人們的要求不相初始值。這種狀況顯然是與人們的要求不相符的,對象是一個實體,它反映了客觀事物符的,對象是一個實體,它反映了客觀事物的屬性的屬性(例如時鐘的時、分、秒的值例如時鐘的時、分、秒的值),是應該,是應該有確定的值的。有確定的值的。類的數據成員是不能在聲明類時初始化的。類的數據成員是不能在聲明類時初始化的。lclass Studentll int sno=10;l string name=wang;l;l編譯錯
3、誤:編譯錯誤:lISO C+ forbids initialization of member snolISO C+ forbids initialization of member namel為什么?為什么?l如果一個類中所有的成員都是公用的,則可以在定如果一個類中所有的成員都是公用的,則可以在定義對象時對數據成員進行初始化。如義對象時對數據成員進行初始化。如lclass Timellpublic: /聲明為公用成員聲明為公用成員l int hour;l int minute;l int sec;l;lTime t1=14,56,30; /將將t1初始化為初始化為14:56:30l但是,如果
4、數據成員是私有的,或者類中有但是,如果數據成員是私有的,或者類中有private或或protected的成員,就不能用這種的成員,就不能用這種方法初始化。方法初始化。l類的封裝性就體現在一部分數據是類的封裝性就體現在一部分數據是不能讓外不能讓外界訪問界訪問的。所以直接在非成員函數中訪問類的。所以直接在非成員函數中訪問類對象的私有或者保護數據是不允許的。對象的私有或者保護數據是不允許的。l類對象的初始化的任務,自然就落到了類的類對象的初始化的任務,自然就落到了類的成員函數身上,因為它們可以訪問私有及保成員函數身上,因為它們可以訪問私有及保護數據成員。護數據成員。l我們將初始化構想成下面的形式:我
5、們將初始化構想成下面的形式:lclass Studentllint sno;ldouble score;lpublic:lvoid init( )l lsno=10;lscore=85;ll. /其他公有成員其他公有成員l; lvoid funllStudent s;ls.init(); /類的初始化類的初始化l.ll將初始化的工作交由將初始化的工作交由init()成員函數無可非議,成員函數無可非議,但讓系統多了一道處理初始化的解釋與執行。但讓系統多了一道處理初始化的解釋與執行。l為了解決這個問題,為了解決這個問題,C+提供了提供了構造函數構造函數(constructor)來處理對象的初始化。
6、構造函數是一來處理對象的初始化。構造函數是一種特殊的成員函數,與其他成員函數不同,種特殊的成員函數,與其他成員函數不同,不需要不需要用戶來調用它用戶來調用它,而是在建立對象時,而是在建立對象時自動執行自動執行。構造。構造函數的名字函數的名字必須與類名同名必須與類名同名,而不能由用戶任意命,而不能由用戶任意命名,以便編譯系統能識別它并把它作為構造函數處名,以便編譯系統能識別它并把它作為構造函數處理。它理。它不具有任何類型不具有任何類型,不返回任何值。構造函數,不返回任何值。構造函數的功能是由用戶定義的,的功能是由用戶定義的,用戶根據初始化的要求設用戶根據初始化的要求設計函數體和函數參數計函數體和
7、函數參數。l#includelusing namespace std;lclass Studentll int sno;l double score;lpublic:l Student( );l void setStudent(int sn,double sc);l int getSno( );l double getScore( );l;Student:Student( ) sno=0; score=0;void Student:setStudent(int sn,double sc) sno=sn; score=sc;lint Student:getSno( )ll return sno;
8、lldouble Student:getScore( )ll return score;llint main( )ll Student a,b;l a.setStudent(10,85);l couta.getSno( ) a.getScore()endl;l coutb.getSno( ) b.getScoreendl;l return 0;ll構造函數沒有返回類型,函數體中也不允許返回值,構造函數沒有返回類型,函數體中也不允許返回值,因為構造函數因為構造函數專門用于創建對象和為其初始化專門用于創建對象和為其初始化,它,它不能隨意被調用不能隨意被調用。沒有返回類型,正顯得它與眾不。沒有返回類
9、型,正顯得它與眾不同。同。注意:注意:l在創建類對象時,構造函數被自動調用。在創建類對象時,構造函數被自動調用。l構造函數沒有返回類型,函數體中也不允許返回構造函數沒有返回類型,函數體中也不允許返回值。值。l構造函數不需用戶調用,也不能被用戶調用。構造函數不需用戶調用,也不能被用戶調用。l構造函數構造函數專門用于專門用于創建對象和為其初始化,一般創建對象和為其初始化,一般不提倡在構造函數中加入與初始化無關的內容。不提倡在構造函數中加入與初始化無關的內容。l如果用戶自己沒有定義構造函數,則如果用戶自己沒有定義構造函數,則C+系統會系統會自動生成一個構造函數自動生成一個構造函數,只是這個構造函數的
10、函數,只是這個構造函數的函數體是空的,也沒有參數,不執行初始化操作。體是空的,也沒有參數,不執行初始化操作。l前面介紹的構造函數不能完全滿足初始化的前面介紹的構造函數不能完全滿足初始化的要求,它只能將對象構造成千篇一律的對象要求,它只能將對象構造成千篇一律的對象值,我們不得不再調用一個初始化成員函數值,我們不得不再調用一個初始化成員函數將數據存到該對象中去。將數據存到該對象中去。l構造函數在參數規定上和普通函數一樣構造函數在參數規定上和普通函數一樣,可,可以有任意多個參數。以有任意多個參數。l#includelusing namespace std;lclass Studentll int s
11、no;l double score;lpublic:l Student(int sn,double sc);l int getSno( );l double getScore( );l;lStudent:Student(int sn,double sc)ll sno=sn;l score=sc;llint Student:getSno()ll return sno;lldouble Student:getScore()ll return score;llint main()ll Student a(10,85),b(11,90);l couta.getSno() a.getScore()end
12、l;l coutb.getSno() b.getScore()endl;l return 0;l輸出:輸出: 851011 90 lC+還提供另一種初始化數據成員的方法還提供另一種初始化數據成員的方法參數初始化表參數初始化表來實現對數據成員的初始化。來實現對數據成員的初始化。這種方法不在函數體內對數據成員初始化,這種方法不在函數體內對數據成員初始化,而是而是在函數首部實現在函數首部實現。class Student int sno; double score;public: Student(int sn,double sc):sno(sn),score(sc) int getSno( ); do
13、uble getScore( );l構造函數可以被重載。構造函數可以被重載。l重載的規則與普通函數重載相同。重載的規則與普通函數重載相同。l#includelusing namespace std;lclass Studentll int sno;l double score;lpublic:l Student( );l Student(int sn);l Student(int sn,double sc);l int getSno( );l double getScore( );l;lStudent:Student()ll sno=0;l score=0;llStudent:Student(
14、int sn)ll sno=sn;l score=0;llStudent:Student(int sn,double sc)ll sno=sn;l score=sc;llint Student:getSno()ll return sno;lldouble Student:getScore()ll return score;llint main()ll Student a,b(11),c(12,98);l couta.getSno() a.getScore()endl;l coutb.getSno() b. getScore()endl;l coutc.getSno() c. getScore(
15、)endl;l return 0;l輸出:輸出:0 0 01112 98 注意:注意:l無參的構造函數屬于默認構造函數。無參的構造函數屬于默認構造函數。一個一個類類只能有一個只能有一個默認構造函數。默認構造函數。l如果在建立對象時選用的是無參構造函數,如果在建立對象時選用的是無參構造函數,應注意正確書寫定義對象的語句。應注意正確書寫定義對象的語句。l盡管在一個類中可以包含多個構造函數,盡管在一個類中可以包含多個構造函數,但是對于每一個對象來說,建立對象時但是對于每一個對象來說,建立對象時只執只執行其中一個行其中一個構造函數,并非每個構造函數都構造函數,并非每個構造函數都被執行。被執行。l構造函
16、數中參數的值既可以通過實參傳遞,構造函數中參數的值既可以通過實參傳遞,也可以指定為某些默認值,即如果用戶不指也可以指定為某些默認值,即如果用戶不指定實參值,編譯系統就使形參取默認值。定實參值,編譯系統就使形參取默認值。lStudent(int sn,double sc=0);lC+規定,規定,每個類必須有一個構造函數每個類必須有一個構造函數。沒有構。沒有構造函數,就不能創建任何對象。造函數,就不能創建任何對象。l若未提供一個類的構造函數(一個都沒有定義),若未提供一個類的構造函數(一個都沒有定義),則則C+提供一個默認的構造函數,該默認構造函數提供一個默認的構造函數,該默認構造函數是個無參構造
17、函數,它僅負責創建對象,而不做任是個無參構造函數,它僅負責創建對象,而不做任何初始化工作。何初始化工作。l只要一個類定義了一個構造函數(不一定是無參只要一個類定義了一個構造函數(不一定是無參構造函數),構造函數),C+就不再提供默認的默認構造函數。就不再提供默認的默認構造函數。l與變量定義類似,在用默認構造函數創建對象時,與變量定義類似,在用默認構造函數創建對象時,如果創建的是全局對象或靜態對象,則對象的值全如果創建的是全局對象或靜態對象,則對象的值全為為0,否則是不確定的。,否則是不確定的。9.2 析構函數析構函數l一個類可能在構造函數里分配資源,這些資一個類可能在構造函數里分配資源,這些資
18、源需要在對象不復存在以前被釋放。源需要在對象不復存在以前被釋放。l例如,如果構造函數打開了一個文件,文件例如,如果構造函數打開了一個文件,文件就要被關閉;如果構造函數從堆中分配了內就要被關閉;如果構造函數從堆中分配了內存,這塊內存在對象消失之前必須被釋放。存,這塊內存在對象消失之前必須被釋放。l析構函數允許類自動完成這些清理工作。析構函數允許類自動完成這些清理工作。l析構函數析構函數也是特殊的類成員函數,它也是特殊的類成員函數,它沒有返沒有返回類型回類型,沒有參數沒有參數,不能隨意調用不能隨意調用,也沒有也沒有重載重載。l析構函數只是在類對象生命期結束的時候,析構函數只是在類對象生命期結束的時
19、候,由系統自動調用由系統自動調用。l析構函數名與類名相同,前面加上析構函數名與類名相同,前面加上。Student( );l#includelusing namespace std;lclass Studentll char* name;lpublic:l Student( );l Student( );l string getName( );l;lStudent:Student()ll name=new char20; /分配堆空間分配堆空間l cout構造函數構造函數endl;llStudent:Student()ll delete name; /釋放堆空間釋放堆空間l cout析構函數析構
20、函數endl;llstring Student:getName()ll return name;llint main()ll Student a;l couta.getName()endl;l return 0;l輸出:輸出:構造函數構造函數noname析構函數析構函數 9.3 調用構造函數和析構函數的順序調用構造函數和析構函數的順序l析構函數以調用構造函數析構函數以調用構造函數相反相反的順序被調用。的順序被調用。 l#includelusing namespace std;lclass Studentll string name;lpublic:l Student(string n);l S
21、tudent( );l;lStudent:Student(string n)ll name=n;l cout構造對象:構造對象:nameendl;llStudent:Student()ll cout析構對象:析構對象:nameendl;llint main( )ll Student s1(a),s2(b);l cout返回到返回到main( )函數函數endl;l return 0;l輸出結果輸出結果構造對象:構造對象:a構造對象:構造對象:b返回到返回到main( )函數函數析構對象:析構對象:b析構對象:析構對象:a析構函數小結:析構函數小結:l析構函數名與類名相同,但前面加上字析構函數名
22、與類名相同,但前面加上字符符。l析構函數無函數返回類型,在這方面與構析構函數無函數返回類型,在這方面與構造函數是一樣的,但析構函數不帶任何參數。造函數是一樣的,但析構函數不帶任何參數。l一個類一個類有一個且只有有一個且只有一個析構函數,這與一個析構函數,這與構造函數不同。析構函數也可以默認。構造函數不同。析構函數也可以默認。l注銷對象時,系統自動調用析構函數。注銷對象時,系統自動調用析構函數。9.4 對象數組對象數組l數組不僅可以由簡單變量組成數組不僅可以由簡單變量組成(例如整型數組例如整型數組的每一個元素都是整型變量的每一個元素都是整型變量),也可以由對象,也可以由對象組成組成(對象數組的每
23、一個元素都是同類的對象對象數組的每一個元素都是同類的對象)。#include using namespace std;class Boxprivate: int height; int width; int length;public: Box(int h=10,int w=12,int len=15): height(h),width(w),length(len) int volume( );int Box:volume( ) return (height*width*length);int main( ) Box a3= Box(10,12,15), Box(15,18,20), Box(
24、16,20,26) ; coutvolume of a0 is a0.volume( )endl; coutvolume of a1 is a1.volume( )endl; coutvolume of a2 is a2.volume( )hour pt所指向的對象中的所指向的對象中的hour成員成員 l(*pt).get_time ( ) 調用調用pt所指向的對象中的所指向的對象中的get_time函數函數lpt-get_time ( ) 調用調用pt所指向的對象中的所指向的對象中的get_time函數函數l對象有地址,存放對象初始地址的指針變量對象有地址,存放對象初始地址的指針變量就是指向
25、對象的指針變量。對象中的成員也就是指向對象的指針變量。對象中的成員也有地址,存放對象成員地址的指針變量就是有地址,存放對象成員地址的指針變量就是指向對象成員的指針變量。指向對象成員的指針變量。1. 指向對象數據成員的指針指向對象數據成員的指針l定義指向對象數據成員的指針變量的方法和定義指向對象數據成員的指針變量的方法和定義指向普通變量的指針變量方法相同。例定義指向普通變量的指針變量方法相同。例如如lint *p1; /定義指向整型數據的指針變量定義指向整型數據的指針變量lp1=&t1.hour; /將對象將對象t1的數據成員的數據成員hour的地址賦給的地址賦給p1,p1指向指向t1.
26、hourlcout*p1endl; /輸出輸出t1.hour的值的值*2. 指向對象成員函數的指針指向對象成員函數的指針l定義指向對象成員函數的指針變量的方法和定義指定義指向對象成員函數的指針變量的方法和定義指向普通函數的指針變量方法有所不同。向普通函數的指針變量方法有所不同。l定義指向公用成員函數的指針變量的一般形式為:定義指向公用成員函數的指針變量的一般形式為:數據類型名數據類型名 (類名類名 *指針變量名指針變量名)(參數表列參數表列);lvoid (Time *p2)( ); /定義定義p2為指向為指向Time類中公用成員函數的指針變量類中公用成員函數的指針變量lp2=&Tim
27、e get_time;l成員函數與普通函數有一個最根本的區別:成員函數與普通函數有一個最根本的區別: 它是類它是類中的一個成員。編譯系統要求在賦值語句中,指針中的一個成員。編譯系統要求在賦值語句中,指針變量的類型必須與賦值號右側函數的類型相匹配,變量的類型必須與賦值號右側函數的類型相匹配,要求在以下要求在以下3方面都要匹配:方面都要匹配: 函數參數的類型和函數參數的類型和參數個數;參數個數;函數返回值的類型;函數返回值的類型;所屬的類。所屬的類。例例l#include lusing namespace std;lclass Timellpublic:l Time(int,int,int);l
28、int hour;l int minute;l int sec;l void get_time( );l;lTime:Time(int h,int m,int s)ll hour=h;l minute=m;l sec=s;llvoid Time:get_time( )ll couthour:minute:secendl;llint main( )ll Time t1(10,13,56);l int *p1=&t1.hour;l cout*p1get_time( );l void (Time:*p3)( );l p3=&Time:get_time;l (t1.*p3)( );l9
29、.6 對象的動態建立和釋放對象的動態建立和釋放l用前面介紹的方法定義的對象是靜態的,在用前面介紹的方法定義的對象是靜態的,在程序運行過程中,對象所占的空間是不能隨程序運行過程中,對象所占的空間是不能隨時釋放的。但有時人們希望在需要用到對象時釋放的。但有時人們希望在需要用到對象時才建立對象,在不需要用該對象時就撤銷時才建立對象,在不需要用該對象時就撤銷它,釋放它所占的內存空間以供別的數據使它,釋放它所占的內存空間以供別的數據使用。這樣可提高內存空間的利用率。用。這樣可提高內存空間的利用率。l可以用可以用new運算符動態建立對象,用運算符動態建立對象,用delete運算符撤銷對象。運算符撤銷對象。
30、l#include lusing namespace std;lclass Studentll int sno;l string name;lpublic:l Student();l Student(int s,string n);l void showInfo();l;lStudent:Student()ll sno=0;l name=no name;llStudent:Student(int s,string n)ll sno=s;l name=n;llvoid Student:showInfo()ll coutsno: snoendl;l coutname: nameshowInfo()
31、;l s2-showInfo();l delete s1;l s1-showInfo(); /可能引發致命錯誤可能引發致命錯誤l9.7 對象的賦值和復制對象的賦值和復制l如果對一個類定義了兩個或多個對象,則這些同類的對象之如果對一個類定義了兩個或多個對象,則這些同類的對象之間可以間可以互相賦值互相賦值,或者說,一個對象的值可以賦給另一個同,或者說,一個對象的值可以賦給另一個同類的對象。這里所指的對象的值是指對象中類的對象。這里所指的對象的值是指對象中所有數據成員所有數據成員的的值。值。l對象之間的賦值也是通過賦值運算符對象之間的賦值也是通過賦值運算符“=”進行的。本來,賦進行的。本來,賦值運算
32、符值運算符“=”只能用來對單個的變量賦值,現在被擴展為兩只能用來對單個的變量賦值,現在被擴展為兩個同類對象之間的賦值,這是通過對賦值個同類對象之間的賦值,這是通過對賦值運算符的重載運算符的重載實現實現的。實際這個過程是通過成員復制來完成的,即將一個對象的。實際這個過程是通過成員復制來完成的,即將一個對象的成員值的成員值一一復制一一復制給另一對象的給另一對象的對應成員對應成員。對象賦值的一般。對象賦值的一般形式為形式為對象名對象名1 = 對象名對象名2;l注意對象名注意對象名1和對象名和對象名2必須屬于同一個類。必須屬于同一個類。l例如例如lStudent s1,s2; /定義兩個同類的對象定義
33、兩個同類的對象lls2=s1; /將將s1賦給賦給s2l說明:說明: l(1) 對象的賦值只對其中的數據成員賦值,而不對成對象的賦值只對其中的數據成員賦值,而不對成員函數賦值。員函數賦值。l(2) 類的數據成員中不能包括類的數據成員中不能包括動態分配的數據動態分配的數據,否則,否則在賦值時可能出現嚴重后果。在賦值時可能出現嚴重后果。l有時需要用到多個完全相同的對象。此外,有時需有時需要用到多個完全相同的對象。此外,有時需要將對象在某一瞬時的狀態保留下來。這就是對象要將對象在某一瞬時的狀態保留下來。這就是對象的復制機制,用一個已有的對象快速地復制出多個的復制機制,用一個已有的對象快速地復制出多個
34、完全相同的對象。如完全相同的對象。如lStudent s1(1,wang);lStudent s2(s1);l其作用是用已有的對象其作用是用已有的對象s1去克隆出一個新對象去克隆出一個新對象s2。l其一般形式為其一般形式為l類名類名 對象對象2(對象對象1);l可以看到:可以看到: 它與前面介紹過的定義對象方式類似,但是括號它與前面介紹過的定義對象方式類似,但是括號中給出的參數不是一般的變量,而是對象。中給出的參數不是一般的變量,而是對象。l在建立對象時調用一個特殊的構造函數在建立對象時調用一個特殊的構造函數復制構造函數復制構造函數(copy constructor)。這個函數的形式是這樣的:
35、。這個函數的形式是這樣的: lStudent:Student(const Student& s)ll sno=s.sno;l name=;ll復制構造函數也是構造函數,但它復制構造函數也是構造函數,但它只有一個參數只有一個參數,這個參數,這個參數是本類的對象是本類的對象(不能是其他類的對象不能是其他類的對象),而且采用對象的引用,而且采用對象的引用的形式的形式(一般約定加一般約定加const聲明聲明,使參數值不能改變,以免在,使參數值不能改變,以免在調用此函數時因不慎而使對象值被修改調用此函數時因不慎而使對象值被修改)。l復制對象的語句復制對象的語句lStudent s2(
36、s1);l實際上也是建立對象的語句,建立一個新對象實際上也是建立對象的語句,建立一個新對象s2。由于在括號內給定的實參是對象,因此由于在括號內給定的實參是對象,因此編譯系統編譯系統就就調用復制構造函數調用復制構造函數(它的形參也是對象它的形參也是對象),而不會去,而不會去調用其他構造函數。調用其他構造函數。s形參形參s是實參是實參s1的引用,因此的引用,因此執行復制構造函數的函數體時,將執行復制構造函數的函數體時,將s1對象中各數據對象中各數據成員的值賦給成員的值賦給s2中各數據成員。中各數據成員。l如果用戶自己未定義復制構造函數,則編譯系統會如果用戶自己未定義復制構造函數,則編譯系統會自動提
37、供自動提供一個一個默認的默認的復制構造函數,其作用只是簡復制構造函數,其作用只是簡單地復制類中每個數據成員。單地復制類中每個數據成員。lC+還提供另一種方便用戶的復制形式,用賦值號代替括號,還提供另一種方便用戶的復制形式,用賦值號代替括號,如如lStudent s3=s1; /用用s1初始化初始化s3l其一般形式為其一般形式為l類名類名 對象名對象名1 = 對象名對象名2;l可以在一個語句中進行多個對象的復制。如可以在一個語句中進行多個對象的復制。如lStudent s2=s1,s3=s2; l可以看出:可以看出: 這種形式與變量初始化語句類似,請與下面定義這種形式與變量初始化語句類似,請與下
38、面定義變量的語句作比較:變量的語句作比較: int a=4,b=a;l這種形式看起來很直觀,用起來很方便。但是其作用都是這種形式看起來很直觀,用起來很方便。但是其作用都是調調用復制構造函數用復制構造函數。l普通構造函數普通構造函數在程序中建立對象時被調用。在程序中建立對象時被調用。l復制構造函數復制構造函數在用已有對象復制一個新對象在用已有對象復制一個新對象時被調用,在以下時被調用,在以下3種情況種情況下需要克隆對象:下需要克隆對象:l 程序中需要新建立一個對象,并用另一個程序中需要新建立一個對象,并用另一個同類的對象對它初始化,如前面介紹的那樣。同類的對象對它初始化,如前面介紹的那樣。lSt
39、udent s2(s1);lStudent s3=s1;l 當當函數的參數為類的對象函數的參數為類的對象時。在調用函數時需要將實參對時。在調用函數時需要將實參對象完整地傳遞給形參,也就是需要建立一個實參的拷貝,這象完整地傳遞給形參,也就是需要建立一個實參的拷貝,這就是按實參復制一個形參,系統是通過調用復制構造函數來就是按實參復制一個形參,系統是通過調用復制構造函數來實現的,這樣能保證形參具有和實參完全相同的值。如實現的,這樣能保證形參具有和實參完全相同的值。如 lvoid fun(Student s) /形參是類的對象形參是類的對象l lint main( )ll Student s1(1,w
40、ang);l fun(s1); /實參是類的對象,調用函數時將復制一個新對象實參是類的對象,調用函數時將復制一個新對象sl return 0;ll 函數的函數的返回值是類的對象返回值是類的對象。在函數調用完畢將返回值帶回函數調用處。在函數調用完畢將返回值帶回函數調用處時。此時需要將函數中的對象復制一個時。此時需要將函數中的對象復制一個臨時對象臨時對象并傳給該函數的調用處。并傳給該函數的調用處。如如 lStudent fun(int s,string n) /函數函數f的類型為的類型為Student類類型類類型ll Student st(s,n);l return st; /返回值是返回值是St
41、udent類的對象類的對象llint main( )ll Student s1;l s1=fun(1,wang);l s1.showInfo();ll以上幾種調用復制構造函數都是由編譯系統自動實現的,不必由用戶自以上幾種調用復制構造函數都是由編譯系統自動實現的,不必由用戶自己去調用,我們只要知道在這些情況下需要調用復制構造函數就可以了。己去調用,我們只要知道在這些情況下需要調用復制構造函數就可以了。對象的復制和對象的賦值對象的復制和對象的賦值lStudent s1(1,zhang);lStudent s2(s1); /對象復制對象復制lStudent s3=s2; /對象復制對象復制lStud
42、ent s4;s4=s1; /對象賦值對象賦值l對象的復制和對象的賦值在概念上和語法上是不同的。對象的復制和對象的賦值在概念上和語法上是不同的。l對象的賦值是對一個對象的賦值是對一個已經存在的對象已經存在的對象賦值,將等號右邊對象賦值,將等號右邊對象數據成員的值賦給等號左邊對象的相應成員。數據成員的值賦給等號左邊對象的相應成員。l對象的復制則是對象的復制則是調用對象復制函數調用對象復制函數。運行下列程序,分析輸出結果運行下列程序,分析輸出結果l#include lusing namespace std;lclass Studentll int sno;l string name;lpublic
43、:l Student();l Student(int,string);l Student(const Student&);l void setSno(int);l void showInfo();l;lStudent:Student()ll cout調用了無參構造函數。調用了無參構造函數。endl;l sno=0;l name=no name;llStudent:Student(int s,string n)ll cout調用了有參構造函數。調用了有參構造函數。endl;l sno=s;l name=n;llStudent:Student(const Student& s)ll
44、 cout調用了復制構造函數。調用了復制構造函數。endl;l sno=s.sno;l name=;llvoid Student:showInfo()ll coutsno: snoendl;l coutname: nameendl;llint main( )ll Student s1(1,wang);l s1.showInfo();l Student s2(s1);l s2.showInfo();l Student s3=s2;l s3.showInfo();l Student s4;l s4=s1;l s4.showInfo();l問題問題1lclass MyClasslpubl
45、ic:l int n;l int *m;l MyClass()m=new int5;l MyClass()delete m;l;lvoid Fun(MyClass mc)l cout3: mc.m0endl;llint main()l MyClass a;l a.m0=3;l cout1: a.m0endl;l Fun(a);l cout2: a.m0endl;l1: 33: 32: 3089840問題出在哪?思考:思考:lclass Studentll int sno;l string name;l int *score;lpublic:l Student();l Student(int s
46、,string n,int sc);l Student(const Student&);l void showInfo();l;這些構造函數這些構造函數如何定義?如何定義?9.8 靜態成員靜態成員l靜態類成員是由關鍵字靜態類成員是由關鍵字static修飾說明的類成修飾說明的類成員。員。類的靜態成員為其所有對象共享,不管類的靜態成員為其所有對象共享,不管有多少對象,靜態成員只有一個存于公用內有多少對象,靜態成員只有一個存于公用內存中存中。l在類定義中,用關鍵字在類定義中,用關鍵字static修飾的數據成員為靜態修飾的數據成員為靜態數據成員,該類產生的所有對象數據成員,該類產生的所有對象共
47、享共享由系統為靜態由系統為靜態成員分配的一塊存儲空間,而這塊存儲空間是成員分配的一塊存儲空間,而這塊存儲空間是在編在編譯時譯時分配的,分配的,在定義對象時不再為靜態成員分配空在定義對象時不再為靜態成員分配空間間。靜態數據實際上是該類所有對象所共有的,它。靜態數據實際上是該類所有對象所共有的,它更像面向過程程序設計的全局變量,可提供同一類更像面向過程程序設計的全局變量,可提供同一類所有對象之間信息交換的捷徑。正因為靜態數據成所有對象之間信息交換的捷徑。正因為靜態數據成員不屬于類的某一特定對象,而是屬于整個類的,員不屬于類的某一特定對象,而是屬于整個類的,所以使用時可用以下格式:所以使用時可用以下
48、格式:類名類名:靜態數據成員名靜態數據成員名lclass Testllprivate:l static int count; /聲明靜態數據成員聲明靜態數據成員lpublic:l Test( )l l +count;l cout對象數量對象數量countendl;l l Test( )l l -count;l cout對象數量對象數量countendl;l l;lint Test:count=0; /定義靜態數據成員定義靜態數據成員lint main( )ll Test a3;l輸出結果:對象數量1對象數量2對象數量3對象數量2對象數量1對象數量0注意:注意:l靜態數據成員在程序一開始運行時就必須存靜態數據成員在程序一開始運行時就必須存在(分配空間),故在(分配空間),故不能不能在任何函數內定義,在任何函數內定義,也也不能不能在類的聲明中定義(只能聲明數據成在類的聲明中定義(只能聲明數據成員),也員),也不能不能在頭文件中類聲明的外部定義。在頭文件中類聲明的外部定義。l靜態數據成員是類的一部分,其定義是類定靜態數據成員是類的一部分,其定義是類定義的一部分,義的一部分,一般將其放在類的內部實現部一般將其
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- GB/T 28062-2025柑橘黃龍病菌實時熒光定量PCR檢測技術規程
- 2025年網絡營銷與傳播策略能力測評試卷及答案
- 2025年數字營銷策略與實施考試試題及答案
- Hydroxymycotrienin-A-生命科學試劑-MCE
- 2025年高中物理高考模擬試卷及答案
- 《地理地形地貌介紹與自然環境保護教案》
- 從詩文中找尋真我:高一語文美文賞析教學教案
- 夏日絕句賞析:五年級語文閱讀理解教案
- 食品購銷合同框架協議
- 2024年上海格致中學高一(下)5月月考英語試題及答案
- 護理試卷試題及答案
- 人文社科班試題及答案
- 2025年中考物理壓軸題分類匯編:單選題(功、能與簡單機械綜合53題)原卷版+解析
- 2025年公路水運工程重大事故隱患判定標準
- 通風維修質保合同協議
- 風景園林設計報告
- DB31/T 1367-2022養老機構服務質量監測與評價規范
- 沙場租地合同協議書模板
- 土地托管合同協議書范本
- 2024年云南省宜良縣事業單位公開招聘醫療衛生崗考前沖刺模擬帶答案
- 八年級英語下學期期末考試(廣州專用)(原卷版)
評論
0/150
提交評論