構(gòu)造函數(shù)與析構(gòu)函數(shù)_第1頁
構(gòu)造函數(shù)與析構(gòu)函數(shù)_第2頁
構(gòu)造函數(shù)與析構(gòu)函數(shù)_第3頁
構(gòu)造函數(shù)與析構(gòu)函數(shù)_第4頁
構(gòu)造函數(shù)與析構(gòu)函數(shù)_第5頁
已閱讀5頁,還剩69頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

構(gòu)造函數(shù)與析構(gòu)函數(shù)1第1頁,共74頁,2023年,2月20日,星期一回想一下變量和函數(shù)參數(shù)的初始化變量

定義與賦值結(jié)合起來:intnumber=9902;函數(shù)

應(yīng)用缺省參數(shù):voidadd(inta=0,intb=0);目的

便于編程、保證變量的值不會無意義,減小程序出錯的可能性。構(gòu)造函數(shù)和析構(gòu)函數(shù)是類中的特殊的成員函數(shù),構(gòu)造函數(shù),創(chuàng)建并初始化類的數(shù)據(jù)成員。析構(gòu)函數(shù),對象撤消時的清理工作,削除對象,釋放內(nèi)存。

2第2頁,共74頁,2023年,2月20日,星期一1.構(gòu)造函數(shù)的特點:程序中用戶不能直接調(diào)用構(gòu)造函數(shù),在創(chuàng)建對象時由系統(tǒng)自動調(diào)用。構(gòu)造函數(shù)是成員函數(shù),它可寫在類體內(nèi)(內(nèi)聯(lián)函數(shù)),也可寫在類體外。構(gòu)造函數(shù)的函數(shù)名與類名相同,沒有返回值,因而不能指定包括void在內(nèi)的任何返回值類型。函數(shù)可有多參數(shù),也可沒有參數(shù),這要根據(jù)需要而定。在類中可定義多個構(gòu)造函數(shù),即構(gòu)造函數(shù)可以重載。構(gòu)造函數(shù)3第3頁,共74頁,2023年,2月20日,星期一2.構(gòu)造函數(shù)應(yīng)用注意點:若自己不定義構(gòu)造函數(shù),編譯程序提供一個缺省構(gòu)造函數(shù)若程序用到指針,則應(yīng)自定義構(gòu)造函數(shù),以減少程序出錯機會.構(gòu)造函數(shù)和析構(gòu)函數(shù)應(yīng)成對定義,以養(yǎng)成良好的編程習(xí)慣3.構(gòu)造函數(shù)的定義格式為:

<類名>::類名(<參數(shù)表>){函數(shù)體}構(gòu)造函數(shù)聲明的格式為:<類名>(<參數(shù)表>);4第4頁,共74頁,2023年,2月20日,星期一4.構(gòu)造函數(shù)與其他成員函數(shù)的區(qū)別在于:1)與類同名2)沒有返回值類型3)系統(tǒng)創(chuàng)建對象時,自動調(diào)用并可用實參對之初始化5.數(shù)據(jù)成員初始化1)賦值方式即構(gòu)造函數(shù)可對對象的數(shù)據(jù)成員進行初始化classX{

private:

inti;

public:

X()

{i=100;}

}5第5頁,共74頁,2023年,2月20日,星期一例:類person包括4個數(shù)據(jù)成員,用來記錄人員信息。生成對象obj,并使用構(gòu)造函數(shù)為obj賦予初始值。#include<iostream.h>classPerson //定義類{private: //類Person的數(shù)據(jù)成員charname[10]; //姓名intage;//年齡intsalary; //薪金chartel[8]; //電話public:

//構(gòu)造函數(shù)PersonPerson(char*xname,intxage,intxsalary,char*xtel);voiddisp();};

6第6頁,共74頁,2023年,2月20日,星期一//函數(shù)Person的定義Person::Person(char*xname,intxage,intxsalary,char*xtel){strcpy(name,xname);//給各數(shù)據(jù)成員提供初值age=xage;salary=xsalary;strcpy(tel,xtel);}//函數(shù)disp的定義voidPerson::disp(){cout<<endl;cout<<"姓名:"<<name<<endl;cout<<"年齡:"<<age<<endl;cout<<"工資:"<<salary<<endl;cout<<"電話:"<<tel<<endl<<endl;}7第7頁,共74頁,2023年,2月20日,星期一voidmain()//主函數(shù){//生成對象obj并初始化Personobj("張立三",25,850,"45672314");obj.disp();//顯示obj}在主函數(shù)中的Personobj("張立三",25,850,"45672314");中完成了以下幾個功能:1.定義并生成了對象obj。2.在生成對象obj的同時,自動調(diào)用相應(yīng)類的構(gòu)造函數(shù)Person3.將初始值"張立三",25,850,"45672314"傳遞給構(gòu)造函數(shù)Person相應(yīng)的形參xname,xage,xsalary,xtel。4.執(zhí)行構(gòu)造函數(shù)體,將相應(yīng)的值賦給相應(yīng)的數(shù)據(jù)成員。程序的執(zhí)行結(jié)果是:姓名:張立三年齡:25工資:850電話:456723148第8頁,共74頁,2023年,2月20日,星期一//Exanple:為類Person增加構(gòu)造函數(shù)#include<string.h>classPerson{private: charm_strName[20]; intm_nAge; intm_nSex;public:

Person(constchar*name,intage,charsex){ strcpy(m_strName,name); m_nAge=age; m_nSex=(sex=='m'?0:1);}voidRegister(char*Name,intAge,charSex); voidGetName(char*Name); intGetAge(); charGetSex();};9第9頁,共74頁,2023年,2月20日,星期一說明:

創(chuàng)建對象時,系統(tǒng)自動調(diào)用對象所屬類的構(gòu)造函數(shù);如果有參數(shù),則利用實參對對象進行初始化。當(dāng)構(gòu)造函數(shù)重載時,由參數(shù)區(qū)分調(diào)用哪個構(gòu)造函數(shù)例:遇到聲明:Personperson1(“Zhang3”,19,’f’);時,編譯器就調(diào)用構(gòu)造函數(shù):Person::person(constchar*,int,char);來創(chuàng)建對象person1并用實參初始化其數(shù)據(jù)成員。如果將構(gòu)造函數(shù)的聲明與定義分開,則聲明時不可帶成員初始化表10第10頁,共74頁,2023年,2月20日,星期一2)構(gòu)造函數(shù)的初始化表

構(gòu)造函數(shù)“頭”與“體”之間的初始化值列表類成員聲明中不允許賦值常量、引用必須初始化其他變量也可以類似初始化

<類名>::<構(gòu)造函數(shù)>(<參數(shù)表>):<變量1>(<初值1>),…,<變量n>(<初值n>){

…}11第11頁,共74頁,2023年,2月20日,星期一類的const常量只能在初始化表里被初始化,因為它不能在函數(shù)體內(nèi)用賦值的方式來初始化classA{…constintSIZE=100;

//錯誤,企圖在類聲明中初始化const數(shù)據(jù)成員intarray[SIZE]; //錯誤,未知的SIZE};12第12頁,共74頁,2023年,2月20日,星期一例:classSillyclass{public:Sillyclass()//此構(gòu)造函數(shù)對成員ten和refi的初始化錯誤。{ten=10;refi=i;}protected:constintten;//常量數(shù)據(jù)成員tenint&refi;//引用refi};說明:1.造成以上錯誤的原因是在Sillyclass類的構(gòu)造函數(shù)進入之后(開始執(zhí)行其函數(shù)體時),對象結(jié)構(gòu)已經(jīng)建立,數(shù)據(jù)成員ten和refi已存在,而其數(shù)據(jù)成員ten為const,而refi為引用,所以在構(gòu)造函數(shù)體內(nèi)不能再對其指派新的值。2.解決以上問題的方法是利用初始化表:在構(gòu)造函數(shù)的括號后面加一“:”和初始化表,初始化表的格式是:數(shù)據(jù)成員名(值),如果有多個時,需要用逗號隔開。13第13頁,共74頁,2023年,2月20日,星期一【例】

類employee中包括私有數(shù)據(jù)成員x,和2個公有函數(shù)成員example、show。程序中使用初始化表是x(215)。#include<iostream.h>//定義類employeeclassemployee{private:constintx;

public:employee();voidshow();};14第14頁,共74頁,2023年,2月20日,星期一//employee的類外定義employee::employee():x(215)//初始化表{…}//show()的定義。voidemployee::show(){cout<<"\nx的值是:"<<x<<endl;}//主函數(shù)voidmain(){//生成對象并為x賦予初始值employeeobj;

//調(diào)用show顯示x的值obj.show();}15第15頁,共74頁,2023年,2月20日,星期一classA{…A(intsize); //構(gòu)造函數(shù)constintSIZE; };A::A(intsize):SIZE(size) //構(gòu)造函數(shù)的初始化表{

…} Aa(100); //對象a的SIZE值為100 Ab(200); //對象b的SIZE值為20016第16頁,共74頁,2023年,2月20日,星期一classX{ private: constintic; int &ir; int i;

public: X():

ic(100), ir(i),

i(200) {i=300; }};17第17頁,共74頁,2023年,2月20日,星期一例#include"iostream.h"classdate{intyear,month,day;

public:

voidsetdate(inty,intm,intd){year=y;month=m;day=d;}intisleapyear();voidprint();date(){year=2000;month=1;day=1;}//說明構(gòu)造函數(shù)

date(inty){year=y;month=1;day=1;}date(inty,intm){year=y;month=m;day=1;}date(inty,intn,intd);};//類定義完

6.構(gòu)造函數(shù)的重載如果一個類中出現(xiàn)了兩個以上的同名的成員函數(shù)時,稱為類的成員函數(shù)的重載。18第18頁,共74頁,2023年,2月20日,星期一intdate::isleapyear(){return(year%4==0&&year%100!=0)||(year%400==0);}voiddate::print(){cout<<year<<"."<<month<<"."<<day<<endl;}date::date(inty,intm,intd)//定義構(gòu)造函數(shù){year=y;month=m;day=d;}19第19頁,共74頁,2023年,2月20日,星期一voidmain(){classdated1,d2(1998);//創(chuàng)建對象并初始化

classdated3(1999,12),d4(2000,12,12);d1.print();d2.print();d3.print();d4.print();}顯示的結(jié)果為:2000.1.11998.1.11999.12.12000.12.1220第20頁,共74頁,2023年,2月20日,星期一例:類Rec定義兩個重載函數(shù),其中一個是無參函數(shù),另一個是有參函數(shù)。它們都是構(gòu)造函數(shù)。#include<iostream.h>//定義類classRec{private:charbookname[30];intnumber;public:Rec();//第1個構(gòu)造函數(shù)說明Rec(char*a,intb);//第2個構(gòu)造函數(shù)說明voidshow();};

21第21頁,共74頁,2023年,2月20日,星期一Rec::Rec()//第1個構(gòu)造函數(shù)定義{strcpy(bookname,'\0');number=0;}Rec::Rec(char*a,intb)//第2個構(gòu)造函數(shù)定義{strcpy(bookname,a);number=b;}voidRec::show()//show的函數(shù)定義{cout<<"booknameis:"<<bookname<<endl;cout<<"booknumberis:"<<number<<endl;}voidmain()//主程序{Recmybook(“VisualC++6.0”,10020);//自動調(diào)用構(gòu)造函數(shù)Rec(char*a,intb)mybook.show();Recyourbook;//自動調(diào)用構(gòu)造函數(shù)Rec()yourbook.show();}22第22頁,共74頁,2023年,2月20日,星期一程序的執(zhí)行結(jié)果是:booknameis:VisualC++6.0booknumberis:10020booknameis:nonamebooknumberis:0可見,當(dāng)出現(xiàn)構(gòu)造函數(shù)重載時,其匹配方式同普通函數(shù)重載時的匹配方式。23第23頁,共74頁,2023年,2月20日,星期一

C++規(guī)定,每個類必須有一個構(gòu)造函數(shù)。如果在類中沒有顯式定義構(gòu)造函數(shù)時,則C++編譯系統(tǒng)在編譯時為該類提供一個默認(rèn)的構(gòu)造函數(shù):

<類名>::<類名>();該默認(rèn)構(gòu)造函數(shù)是個無參函數(shù),它僅負(fù)責(zé)創(chuàng)建對象,而不做任何初始化工作。如果在類聲明中已經(jīng)聲明、定義了構(gòu)造函數(shù)(不一定是無參構(gòu)造函數(shù)),C++編譯系統(tǒng)就不再提供默認(rèn)的構(gòu)造函數(shù)。當(dāng)構(gòu)造函數(shù)有缺省參數(shù)時,稱為具有缺省參數(shù)的構(gòu)造函數(shù),在使用時要防止二義性。7.默認(rèn)構(gòu)造函數(shù)與缺省構(gòu)造函數(shù)24第24頁,共74頁,2023年,2月20日,星期一但是,一個類類型如果有const成員或引用成員,就不能使用缺省的構(gòu)造函數(shù)。必須使用用戶定義的構(gòu)造函數(shù)進行初始化;而且只能使用表達式表的方式進行初始化。classX{constinta;constint&r;};XXobj;//錯誤class

X{constinta;constint&r;X():a(9),r(a){}

…};XXobj;//正確classX{constinta;constint&r;X(){a=9;r=a;}

//錯誤

…};25第25頁,共74頁,2023年,2月20日,星期一例classMyclass//定義類Myclass{private:intmember;

public:

Myclass();Myclass(inti);……};Myclass::Myclass()

//構(gòu)造函數(shù)Myclass{member=10;}Myclass::Myclass(inti=10)//構(gòu)造函數(shù)Myclass(inti),該函數(shù)的形參i為缺省參數(shù){member=i;}26第26頁,共74頁,2023年,2月20日,星期一voidmain(){Myclassx(20);Myclassy; //產(chǎn)生二義性,無法確定自動調(diào)用哪個構(gòu)造函數(shù)完成對象的構(gòu)造……}27第27頁,共74頁,2023年,2月20日,星期一拷貝構(gòu)造函數(shù)首先是構(gòu)造函數(shù),創(chuàng)建對象時被調(diào)用,其功能是將一個已存在的對象的數(shù)據(jù)成員拷貝給正在創(chuàng)建的的另一個同類對象。具有以下特點:具有構(gòu)造函數(shù)的所有特性。該函數(shù)只有一個參數(shù),并且是對對象的引用對每個類,編譯系統(tǒng)會自動生成一個拷貝構(gòu)造函數(shù),作為該類的共有成員。8.復(fù)制構(gòu)造函數(shù)28第28頁,共74頁,2023年,2月20日,星期一用戶可以自定義一個,其定義格式為:

<類名>::<類名>(const<類名>&<引用名>)

{

<函數(shù)體>}其中,參數(shù)是一個被const修飾的引用,從而說明在函數(shù)體中對該引用所引用的對象是不能修改的。29第29頁,共74頁,2023年,2月20日,星期一例:使用缺省拷貝構(gòu)造函數(shù)

#include"iostream.h"classPoint{intx,y;

public:voidsetpoint(inta,intb){x=a;y=b;}intgetx(){returnx;}intgety(){returny;}Point(inta,intb){x=a;y=b;}};voidmain(){classPointp1(12,12),p2(p1);cout<<p2.getx()<<""<<p2.gety()<<endl;}顯示結(jié)果為:121230第30頁,共74頁,2023年,2月20日,星期一例:使用自定義拷貝構(gòu)造函數(shù)。

#include"iostream.h"classPoint{intx,y;public:

voidsetpoint(inta,intb){x=a;y=b;}intgetx(){returnx;}intgety(){returny;}Point(inta,intb){x=a;y=b;}Point(Point&p);//說明拷貝構(gòu)造函數(shù)};Point::Point(Point&p)//定義拷貝構(gòu)造函數(shù)

{x=p.x;y=p.y;cout<<"Copy-initializationcontructorcalled!"<<endl;}31第31頁,共74頁,2023年,2月20日,星期一voidmain(){classPointp1(12,12),p2(p1);cout<<p2.getx()<<""<<p2.gety()<<endl;}程序執(zhí)行后的顯示結(jié)果為:Copy-initializationcontructorcalled!1212例:使用拷貝構(gòu)造函數(shù)。#include"iostream.h"classPoint;classPointf(Pointq);classPoint{intx,y;32第32頁,共74頁,2023年,2月20日,星期一public:

voidsetpoint(inta,intb){x=a;y=b;}intgetx(){returnx;}intgety(){returny;}Point(){x=0;y=0;};Point(inta,intb){x=a;y=b;}Point(constPoint&p);};Point::Point(constPoint&p){x=p.x;y=p.y;cout<<"copy-Initializtioncompleted!\n";}voidmain(){classPointp1(12,12),p2(p1),p3;cout<<p2.getx()<<""<<p2.gety()<<endl;cout<<"--------------------"<<endl;p3=f(p2);33第33頁,共74頁,2023年,2月20日,星期一cout<<p3.getx()<<""<<p3.gety()<<endl;}classPointf(classPointq){intx,y;x=q.getx()+10;y=q.gety()+10;Pointr(x,y);returnr;}程序執(zhí)行后的顯示結(jié)果為:copy-Initializtioncompleted!1212--------------------copy-Initializtioncompleted!copy-Initializtioncompleted!222234第34頁,共74頁,2023年,2月20日,星期一在上面的程序中,拷貝構(gòu)造函數(shù)被調(diào)用了3次。第一次是在main()函數(shù)中執(zhí)行classPointp2(p1);時;第二次是在調(diào)用函數(shù)f()時,實參p2給形參對象q進行初始化時,即實參向形參傳遞值時;第三次是在執(zhí)行函數(shù)f()中的返回語句returnr;時,系統(tǒng)用返回值初始化一匿名的Point對象時使用了拷貝構(gòu)造函數(shù)。在調(diào)用f()函數(shù)返回主函數(shù)main()后,用賦值運算符將匿名對象的值賦給對象p3,然后釋放匿名對象。35第35頁,共74頁,2023年,2月20日,星期一通過上面的例題分析,在下面三種情況系統(tǒng)自動調(diào)用拷貝構(gòu)造函數(shù)來初始化一個對象:明確表示由一個對象初始化一個對象。例如,上例main()中:

classPointp1(12,12),p2(p1),p3;當(dāng)對象作為函數(shù)實參傳遞給函數(shù)形參時。例如,上例main()中:

p3=f(p2);當(dāng)對象作為函數(shù)的返回值時。例如,上例main()中:

returnr;

36第36頁,共74頁,2023年,2月20日,星期一析構(gòu)函數(shù)

與構(gòu)造函數(shù)(創(chuàng)建對象)相對應(yīng)的是析構(gòu)函數(shù)(撤消對象:當(dāng)一個對象的生存期結(jié)束時,系統(tǒng)自動調(diào)用析構(gòu)函數(shù),返還它所占據(jù)的內(nèi)存空間)析構(gòu)函數(shù)定義形式:

<類名>::~<類名>();37第37頁,共74頁,2023年,2月20日,星期一析構(gòu)函數(shù)是成員函數(shù),它可寫在類體內(nèi),也可寫在類體外。析構(gòu)函數(shù)名與類名相同,但前面須加~析構(gòu)函數(shù)不得帶任何參數(shù),不能重載一個類定義中只能有一個析構(gòu)函數(shù)析構(gòu)函數(shù)不返回任何值,用void也不許析構(gòu)函數(shù)中不能調(diào)用C++的庫函數(shù)exit(),以防形成無限遞歸。但可以調(diào)用庫函數(shù)abort(),終止整個程序。1.析構(gòu)函數(shù)的特點38第38頁,共74頁,2023年,2月20日,星期一如果在類的定義中沒有顯式地定義析構(gòu)函數(shù),則系統(tǒng)將自動產(chǎn)生一個缺省析構(gòu)函數(shù),函數(shù)體為空:

<類名>::~<類名>(){}對于一個簡單的類來說,大多可以直接使用系統(tǒng)提供的默認(rèn)析構(gòu)函數(shù)。但是,如果在類的對象中分配有動態(tài)內(nèi)存(如:用new申請分配的內(nèi)容)時,就必須為該類提供適當(dāng)?shù)奈鰳?gòu)函數(shù),完成清理工作。對象被析構(gòu)的順序與對象建立時的順序正好相反。即最后構(gòu)造的對象先被析構(gòu)。39第39頁,共74頁,2023年,2月20日,星期一例:當(dāng)你進入圖書館閱覽室借書閱覽時,你就成為了一個閱覽室的閱覽人(對象),接什么書是由一進去就完成的(構(gòu)造)。當(dāng)你要撤離閱覽室(撤消)對象時,你必須先歸還圖書(析構(gòu))才能順當(dāng)?shù)仉x開。示例構(gòu)造函數(shù)和析構(gòu)函數(shù)的執(zhí)行次序、構(gòu)造函數(shù)的初始化表40第40頁,共74頁,2023年,2月20日,星期一#include<iostream.h>classEx{private: intda; charch; public: Ex(intx,charc='c');~Ex() {cout<<'B'<<endl;} voidoutdata(void) { cout<<ch<<“,”<<da<<endl; }};41第41頁,共74頁,2023年,2月20日,星期一voidmain(){Exx(3,'a'),y(1);Exz[2]={Ex(10,'a'),Ex(1,'d')};x.outdata();y.outdata();z[0].outdata();}Ex::Ex(intx,charc):da(x),ch(c) { cout<<'A'<<endl; }輸出結(jié)果:AAAAa,3c,1a,10BBBB42第42頁,共74頁,2023年,2月20日,星期一[例]使用析構(gòu)造函數(shù)。#include"iostream.h"classPoint;classPointf(Pointq);classPoint{intx,y;public:

voidsetpoint(inta,intb){x=a;y=b;}intgetx(){returnx;}intgety(){returny;}Point(){x=0;y=0;};Point(inta,intb){x=a;y=b;}Point(constPoint&p);~Point(){cout<<"Destructorcalled!\n";}};43第43頁,共74頁,2023年,2月20日,星期一Point::Point(constPoint&p){x=p.x;y=p.y;cout<<"copy-Initializtioncompleted!\n";}voidmain(){classPointp1(12,12),p2(p1),p3;cout<<p2.getx()<<""<<p2.gety()<<endl;cout<<"--------------------"<<endl;p3=f(p2);cout<<p3.getx()<<""<<p3.gety()<<endl;}classPointf(classPointq){intx,y;x=q.getx()+10;y=q.gety()+10;Pointr(x,y);returnr;}44第44頁,共74頁,2023年,2月20日,星期一程序執(zhí)行后的顯示結(jié)果為:copy-Initializtioncompleted!1212--------------------copy-Initializtioncompleted!copy-Initializtioncompleted!Destructorcalled!Destructorcalled!Destructorcalled!2222Destructorcalled!Destructorcalled!Destructorcalled!45第45頁,共74頁,2023年,2月20日,星期一在上例中,退出函數(shù)f()時,函數(shù)中定義的兩個對象q、r被釋放,系統(tǒng)自動調(diào)用析構(gòu)函數(shù)2次。在main()函數(shù)中,用賦值運算符將匿名對象賦給對象p3后,系統(tǒng)釋放匿名對象,此時又調(diào)用一次析構(gòu)函數(shù),共調(diào)用了3次析構(gòu)函數(shù)。最后,退出整個程序時,系統(tǒng)釋放p1、p2和p3三個對象,又3次調(diào)用析構(gòu)函數(shù)。46第46頁,共74頁,2023年,2月20日,星期一【例】類Teacher的構(gòu)造函數(shù)為name申請存儲空間,在析構(gòu)函數(shù)中釋放該空間。#include<windows.h>#include<iostream.h>//定義類classTeacher{private:char*name;intage;

public:

//說明構(gòu)造函數(shù)Teacher

Teacher(char*i,inta){name=newchar[strlen(i)+1];

//用new為name成員分配堆內(nèi)存strcpy(name,i);age=a;cout<<"\n執(zhí)行構(gòu)造函數(shù)Teacher"<<endl;};47第47頁,共74頁,2023年,2月20日,星期一//說明析構(gòu)函數(shù)~Teacher~Teacher(){deletename;cout<<"執(zhí)行析構(gòu)函數(shù)~Teacher"<<endl<<endl;};voidshow();};voidTeacher::show(){cout<<"姓名:"<<name<<""<<"年齡:"<<age<<endl;}voidmain()//主程序{Teacherobj("張立三",25);obj.show();}程序的執(zhí)行結(jié)果是:執(zhí)行構(gòu)造函數(shù)Teacher姓名:張立三年齡:25執(zhí)行析構(gòu)函數(shù)~Teacher48第48頁,共74頁,2023年,2月20日,星期一一個對象可以用作另一個對象的成員當(dāng)一個類的成員是某一個類的對象時,該對象就稱為子對象,子對象實際上是對象成員。在C++中,當(dāng)把一個類的對象作為新類的數(shù)據(jù)員時,則新類的定義格式可表示為:classX{類名1成員名1;類名2成員名2;……類名n成員名n;……//其它成員};49第49頁,共74頁,2023年,2月20日,星期一如果一個類A的對象作為另一個類B的數(shù)據(jù)成員,則在類B的對象創(chuàng)建過程中,調(diào)用其構(gòu)造函數(shù)的過程中,數(shù)據(jù)成員(類A的對象)會自動調(diào)用類A的構(gòu)造函數(shù)。但應(yīng)注意:如果類A的構(gòu)造函數(shù)為有參函數(shù)時,則在程序中必須在類B的構(gòu)造函數(shù)的括號后面加一“:”和被調(diào)用的類A的構(gòu)造函數(shù),且調(diào)用類A的構(gòu)造函數(shù)時的實參值必須來自類B的形參表中的形參。這種方法稱為初始化表的方式調(diào)用構(gòu)造函數(shù)。如:以上面定義的類X為例,在對類X的對象進行初始化時,必須首先初始化其中的子對象,即必須首先調(diào)用這些子對象的構(gòu)造函數(shù)。因此,類X的構(gòu)造函數(shù)的定義格式應(yīng)為:X::X(參數(shù)表0):成員1(參數(shù)表1),成員2(參數(shù)表2),…,成員n(參數(shù)表n){……}50第50頁,共74頁,2023年,2月20日,星期一其中,參數(shù)表1提供初始化成員1所需的參數(shù),參數(shù)表2提供初始化成員2所需的參數(shù),依此類推。并且這幾個參數(shù)表的中的參數(shù)均來自參數(shù)表0,另外,初始化X的非對象成員所需的參數(shù),也由參數(shù)表0提供。在構(gòu)造新類的對象過程中,系統(tǒng)首先調(diào)用其子對象的構(gòu)造函數(shù),初始化子對象;然后才執(zhí)行類X自己的構(gòu)造函數(shù),初始化類中的非對象成員。對于同一類中的不同子對象,系統(tǒng)按照它們在類中的說明順序調(diào)用相應(yīng)的構(gòu)造函數(shù)進行初始化,而不是按照初始化表的順序。51第51頁,共74頁,2023年,2月20日,星期一【例】以下定義了三個Student、Teacher和Tourpair,其中Student類的對象和Teacher類的對象作為了Tourpair的數(shù)據(jù)成員,觀察對象的構(gòu)造過程和構(gòu)造函數(shù)被執(zhí)行的順序。#include<iostream.h>classStudent{public:

Student(){cout<<”constructstudent.\n”;semeshours=100;gpa=3.5;}protected:intsemeshours;floatgpa;};52第52頁,共74頁,2023年,2月20日,星期一classTeacher{public:Teacher(){cout<<”constructTeacher.\n”;}};classTourpair{public:Tourpair(){cout<<”constructtourpair.\n”;nomeeting=0;}

protected:Studentstudent;Teacherteacher;intnomeeting;};53第53頁,共74頁,2023年,2月20日,星期一voidmain(){Tourpairtp;cout<<”backinmain.\n”;}其執(zhí)行結(jié)果是:

constructstudent.constructteacher.constructtourpair.backinmain.由此可見:主函數(shù)main()運行開始時,遇到要創(chuàng)建Tourpair類的對象,于是調(diào)用其構(gòu)造函數(shù)Tourpair(),該構(gòu)造啟動時,首先分配對象空間(包含一個Student對54第54頁,共74頁,2023年,2月20日,星期一象、一個Teacher對象和一個int型數(shù)據(jù)),然后根據(jù)其在類中聲明的對象成員的次序依次調(diào)用其構(gòu)造函數(shù)。即先調(diào)用Student()構(gòu)造函數(shù),后調(diào)用Teacher()構(gòu)造函數(shù),最后才執(zhí)行它自己的構(gòu)造函數(shù)的函數(shù)體。由于上例中Tourpair類的數(shù)據(jù)成員student和teacher的構(gòu)造函數(shù)都是無參函數(shù),所以系統(tǒng)在構(gòu)造student和teacher對象時會自動調(diào)用各自的構(gòu)造函數(shù)Student()和Teacher(),而不需要用初始化表的方式去調(diào)用。55第55頁,共74頁,2023年,2月20日,星期一【例】試分析以下程序的執(zhí)行結(jié)果:#include<iostream.h>#include<string.h>classStudent{public:Student(char*pName="Noname"){cout<<"構(gòu)造新同學(xué):"<<pName<<endl;strncpy(name,pName,sizeof(name));name[sizeof(name)-1]='\0';}Student(Student&s){cout<<"構(gòu)造copyof"<<<<endl;strcpy(name,"copyof");strcat(name,);}56第56頁,共74頁,2023年,2月20日,星期一

~Student(){cout<<"析構(gòu)"<<name<<endl;}protected:charname[40];};classTutor{public:

Tutor(Student&s):student(s)//此為初始化表,調(diào)用Student的拷貝構(gòu)造函數(shù){cout<<"構(gòu)造指導(dǎo)教師\n";}

protected:Studentstudent;};57第57頁,共74頁,2023年,2月20日,星期一voidmain(){Studentst1;//此處調(diào)用Student的構(gòu)造函數(shù)Student(char*pName="Noname")

Studentst2("zhang");

//同上

Tutortutor(st2);

//此處調(diào)用Tutor的構(gòu)造函數(shù)Tutor(Student&s),在構(gòu)造tutor對象的過程中,用初始化表調(diào)用Student類的拷貝構(gòu)造函數(shù)Student(Student&s)}執(zhí)行結(jié)果如下:構(gòu)造新同學(xué):Noname構(gòu)造新同學(xué):zhang構(gòu)造copyofzhang構(gòu)造指導(dǎo)教師析構(gòu)copyofzhang析構(gòu)zhang析構(gòu)Noname58第58頁,共74頁,2023年,2月20日,星期一注意:顯式的構(gòu)造函數(shù)與析構(gòu)函數(shù)并不一定要成對出現(xiàn)如果在定義構(gòu)造函數(shù)時利用了new運算符,那么必須定義析構(gòu)函數(shù),利用delete運算符撤消對象時釋放由new申請的空間(例:拷貝構(gòu)造函數(shù))59第59頁,共74頁,2023年,2月20日,星期一1指向類成員的指針定義指向類的數(shù)據(jù)成員和函數(shù)成員的指針。定義格式如下:<類型><類名>::*<指針名><類型>(<類名>::*<指針名>)(參數(shù)表)[例]指向類的數(shù)據(jù)成員、函數(shù)成員和指向?qū)ο笾羔樀膽?yīng)用#include"iostream.h"

classPoint{intx,y;public:

Point(inta=0,intb=0){x=a;y=b;}voidmovedx(inta,intb){x=x+a;y=y+b;}inttemp;對象與指針60第60頁,共74頁,2023年,2月20日,星期一voidprint(){cout<<x<<""<<y<<""<<temp<<endl;}};voidmain(){classPointp1(1,1),*pr;//定義指向?qū)ο笾羔榠ntPoint::*pdm,*pi;//定義指向數(shù)據(jù)成員指針void(Point::*pfm)(int,int);//定義指向成員函數(shù)指針

pdm=&Point::temp;//指定所指向的成員p1.*pdm=11;//使用指針訪問對象的數(shù)據(jù)成員p1.print();cout<<"-----------------"<<endl;pfm=Point::movedx;//指定所指向的成員函數(shù)(p1.*pfm)(1,1);//使用指針訪問對象的成員函數(shù)p1.print();61第61頁,共74頁,2023年,2月20日,星期一cout<<"-----------------"<<endl;pr=&p1;pr->temp=22;pr->movedx(2,2);pr->print();cout<<"-----------------"<<endl;pi=&(p1.temp);*pi=33;p1.print();}程序的輸出結(jié)果為:1111-----------------2211-----------------4422-----------------443362第62頁,共74頁,2023年,2月20日,星期一使用指向數(shù)據(jù)成員指針的步驟如下:

定義指向數(shù)據(jù)成員指針。指定指向數(shù)據(jù)成員指針指向類的哪個數(shù)據(jù)成員,其格式為:<指向數(shù)據(jù)成員指針名>=&<類名>::<數(shù)據(jù)成員名>

使用指向數(shù)據(jù)成員指針對某個類的對象的成員進行操作,其引用格式為:

<對象名>.*<指向數(shù)據(jù)成員指針名>其中.*是成員指針選擇運算符。63第63頁,共74頁,2023年,2月20日,星期一使用指向成員函數(shù)指針的步驟如下:定義指向成員函數(shù)的指針。指定指向成員函數(shù)指針指向類的哪個成員函數(shù),其格式為:

<指向成員函數(shù)指針名>=<類名>::<成員函數(shù)名>

使用指向成員函數(shù)指針對類的某個對象的成員函數(shù)進行操作,其引用格式為:

(<對象名>.*<指向成員函數(shù)指針名>)(實參表)

(<指向?qū)ο蟮闹羔?gt;->*<指向成員函數(shù)指針名>)(實參表)其中->*是成員指針選擇運算符。64第64頁,共74頁,2023年,2月20日,星期一2.對象指針對象可以直接引用,也可以通過對象指針來引用。定義對象person1并初始化參數(shù):

Personperson1(“Zhang”,19,’f’);聲明指向?qū)ο蟮闹羔榩tr:Person*ptr=&person1;通過指針訪問對象的成員:ptr->GetAge();65第65頁,共74頁,2023年,2月20日,星期一對象的指針、對象的動態(tài)建立與釋放:Person*pPerson=newPerson;……deletepPerson;所謂堆對象是指在程序的運行過程中建立的對象66第66頁,共74頁,2023年,2月20日,星期一【例】#include“iostream.h”classPoint{intx,y;public:

Point(inta=0,intb=0){x=a;y=b;}voidprint(){cout<<x<<""<<y<<endl;}};voidmain(){Point*p;p=newPoint[10];//創(chuàng)建對象時,調(diào)用構(gòu)造函數(shù)。if(!p){cout<<"Allocationfailure\n";return;}for(inti=0;i<10;i++)p[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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論