版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
C++程序設計教程(第二版)第九章對象生滅11/17/20221C++程序設計教程(第二版)第九章對象生滅11/9/20第九章內容構造函數(shù)設計構造函數(shù)的重載類成員初始化構造順序拷貝構造函數(shù)析構函數(shù)對象轉型與賦值11/17/20222第九章內容構造函數(shù)設計11/9/202221.構造函數(shù)設計
初始化要求定義一個對象,其形式與定義一個變量相似,但更具意義。對象與變量的不同在于對象對應于事物,要求從誕生之時起便有明確的意義.對象必須建立一種初始化機制,以滿足在編程中可以針對實際問題所提出的要求而賦給一個有意義的初值。創(chuàng)建一個對象,若創(chuàng)建的是全局對象,則以全0的模式表示對象,若創(chuàng)建局部對象,則以隨機值表示對象。11/17/202231.構造函數(shù)設計
初始化要求定義一個對象,對象的初始化不是簡單的參數(shù)與成員對應,而是聯(lián)系參數(shù)到成員的過程.封裝性要求StructPoint{intx,y;};Pointd={2,3};classPoint{intx,y;//…};Pointd={2,3};正確錯誤封裝性的要求杜絕了這種初始化形式,事實上,這種形式根本不能完成對象的初始化過程中的校驗和計算工作。對象通常是一個復雜的實體,在構建對象過程中,并不一定是一個初值對應一個對象分量。許多時候,一個初值只是傳遞一個信息,告訴對象的創(chuàng)建工作應怎么進行。封裝性要求對象創(chuàng)建中按傳遞的信息進行一個過程化的初始化工作。11/17/20224對象的初始化不是簡單的參數(shù)與成員對應,而是聯(lián)系函數(shù)形式構造函數(shù)(constructor)是與類名同名的特殊的成員函數(shù),當定義該類的對象時,構造函數(shù)將被自動調用以實現(xiàn)對該對象的初始化。構造函數(shù)不能有返回值,因而不能指定包括void在內的任何返回值類型。構造函數(shù)的定義體可與其它成員函數(shù)成員一樣,放在類內或類外都可。構造函數(shù)的定義格式為:類名(形參說明){函數(shù)體}構造函數(shù)既可定義成有參函數(shù),也可義成無參函數(shù),要根據(jù)問題的需要來定。全局變量和靜態(tài)變量在定義時,將自動賦初值為0;局部變量在定義時,其初始值不固定的。而當對象被定義時,由于對象的意義表達了現(xiàn)實世界的實體,所以一旦定義對象,就必須有一個有意義的初始值,在C++中,在定義對象的同時,給該對象初始化的方法就是利用構造函數(shù)。11/17/20225函數(shù)形式構造函數(shù)(constructor)是與類名同名的特殊例:類person包括4個數(shù)據(jù)成員,用來記錄人員信息。生成對象obj,并使用構造函數(shù)為obj賦予初始值。#include<windows.h>#include<iostream.h>classPerson //定義類{private: //類Person的數(shù)據(jù)成員charname[10]; //姓名intage; //年齡intsalary; //薪金chartel[8]; //電話public: //構造函數(shù)PersonPerson(char*xname,intxage,intxsalary,char*xtel);voiddisp();};//函數(shù)Person的定義Person::Person(char*xname,intxage,intxsalary,char*xtel){strcpy(name,xname);//給各數(shù)據(jù)成員提供初值age=xage;salary=xsalary;strcpy(tel,xtel);}11/17/20226例:類person包括4個數(shù)據(jù)成員,用來記錄人員//函數(shù)disp的定義voidPerson::disp(){cout<<endl;cout<<"姓名:"<<name<<endl;cout<<"年齡:"<<age<<endl;cout<<"工資:"<<salary<<endl;cout<<"電話:"<<tel<<endl<<endl;}//主函數(shù)voidmain(){//生成對象obj并初始化Personobj("張立三",25,850,"45672314");//顯示objobj.disp();}11/17/20227//函數(shù)disp的定義11/9/20227程序的執(zhí)行結果是:姓名:張立三年齡:25工資:850電話:45672314在主函數(shù)中的Personobj("張立三",25,850,"45672314");中完成了以下幾個功能:1.定義并生成了對象obj。2.在生成對象obj的同時,自動調用相應類的構造函數(shù)Person3.將初始值"張立三",25,850,"45672314"傳遞給構造函數(shù)Person相應的形參xname,xage,xsalary,xtel。4.執(zhí)行構造函數(shù)體,將相應的值賦給相應的數(shù)據(jù)成員。11/17/20228程序的執(zhí)行結果是:11/9/20228一次性對象創(chuàng)建對象時如果不給出對象名,直接以類名調用構造函數(shù),則產生一個無名對象。無名對象經常在參數(shù)傳遞時使用。例如:cout<<Date(2003,12,23);Date(2003,12,23)是一個對象,該對象在做了<<操作后便煙消云散了,所以這種對象一般用在創(chuàng)建后不需要反復使用的場合。11/17/20229一次性對象創(chuàng)建對象時如果不給出對象名,直接以
2.構造函數(shù)重載
構造函數(shù)畢竟是函數(shù),是函數(shù)就可以重載。不但可以重載,還可以設置默認參數(shù)。如果一個類中出現(xiàn)了兩個以上的同名的成員函數(shù)時,稱為類的成員函數(shù)的重載。classDate{public:Date(conststring&s);//重載Date(inty=2003,intm=12,intd=1);//參數(shù)默認//...};intmain(){Dated(“2006-12-26”);Datee(2000,12,25);Datef(2001,10);Dateg(2002);Dateh;//...}11/17/202210
2.構造函數(shù)重載
構造函數(shù)畢竟是函數(shù),是函Dateh;這行代碼似乎是一個錯誤,對于對象的創(chuàng)建,即對于無參的構造函數(shù)的調用,應該是g(),加上類名,即寫成:Dateg();但是,從語法上來講,這個語句也是名叫g的返回臨時Date對象的函數(shù)聲明!因此,C++語言在設計時,為了區(qū)別無初始化的對象定義和返回類對象的無參函數(shù)聲明的差別,也為了保持無初始化變量定義與無初始化(無參)對象定義的一致性,規(guī)定無參對象定義語句為:inta;//變量定義intb;//返回整型值的無參函數(shù)聲明Dateg;//無參對象定義,加空括號后就成了無參函數(shù)聲明Dateg();//返回類對象的無參函數(shù)聲明11/17/202211Dateh;這行代碼似乎是一個錯誤,對于對象的創(chuàng)建,即對對于返回對象值的有參函數(shù)聲明和有初始化的對象定義語句,由于函數(shù)聲明中的參數(shù)有類型引導,而對象定義的初始化中無類型引導,它們本身(或在編譯器看來)是可以區(qū)分的:Datee(2002);//對象定義Datee(inty);//函數(shù)聲明11/17/202212對于返回對象值的有參函數(shù)聲明和有初始化的對象C++規(guī)定,每個類必須有一個構造函數(shù)。如果在類中沒有顯式定義構造函數(shù)時,則C++編譯系統(tǒng)在編譯時為該類提供一個默認的構造函數(shù),該默認構造函數(shù)是個無參函數(shù),它僅負責創(chuàng)建對象,而不做任何初始化工作。classDate{public://相當于定義了Date(){}};intmain(){Dated;//ok//...}與變量定義相似,在用默認構造函數(shù)創(chuàng)建對象時,如果創(chuàng)建的是全局對象或靜態(tài)對象,則對象的默認值為0,否則對象的初始值是不定的。11/17/202213C++規(guī)定,每個類必須有一個構造函數(shù)。如果在類中沒有顯式定只要一個類定義了一個構造函數(shù)(不一定是無參構造函數(shù)),C++編譯系統(tǒng)就不再提供默認的構造函數(shù)。任何其他的構造函數(shù)定義,都將阻止默認無參空函數(shù)的產生:classDate{public:Date(inty,intm,intd){}//...};intmain(){Dated;//error//...}11/17/202214只要一個類定義了一個構造函數(shù)(不一定是無參構造函數(shù)),11/當構造函數(shù)有缺省參數(shù)時,稱為具有缺省參數(shù)的構造函數(shù),在使用時要防止二義性。如:classMyclass//定義類Myclass{private:intmember;public:Myclass();Myclass(inti);……}Myclass:Myclass()//構造函數(shù)Myclass{member=10;}11/17/202215當構造函數(shù)有缺省參數(shù)時,稱為具有缺省參數(shù)的構Myclass:Myclass(inti=10)//構造函數(shù)Myclass(inti),該函數(shù)//的形參i為缺省參數(shù){member=i;}voidmain(){Myclassx(20);Myclassy; //產生二義性,無法確定自動調用哪個構造//函數(shù)完成對象的構造……}11/17/202216Myclass:Myclass(inti=10)//構造回顧:上節(jié)課主要講了構造函數(shù)的概念、意義及定義方式、構造函數(shù)的重載。11/17/202217回顧:11/9/202217
3.類成員初始化
默認調用的無參構造函數(shù)在類定義中有數(shù)據(jù)成員和成員函數(shù),數(shù)據(jù)成員可以是內部數(shù)據(jù)類型的變量實體,也可以是對象實體。如果一個類A的對象作為另一個類B的數(shù)據(jù)成員,則在類B的對象創(chuàng)建過程中,調用其構造函數(shù)的過程中,數(shù)據(jù)成員(類A的對象)會自動調用類A的構造函數(shù)。這樣就會面臨一些問題。例:有一個學號類和一個學生類,學生類中包含了學號類的對象,因此在構造學生類對象時,面臨著學號類對象的構造。11/17/202218
3.類成員初始化
默認調用的無參構造函數(shù)classStudentID{intvalue;public:
StudentID(){staticintnextStudentID=0;value=++nextStudentID;cout<<"Assigningstudentid"<<value<<"\n";}};//-----------------------------------classStudent{stringname;
StudentIDid;public:Student(stringn="noName"){cout<<"Constructingstudent"+n+"\n";name=n;}};//-----------------------------------intmain(){Students("Randy");}//==============================在學生類的構造函數(shù)中并沒有看到學號類對象初始化的痕跡,而數(shù)據(jù)成員name倒被賦了初值。從運行的結果看,當學生類對象被構造時,一個學號對象也創(chuàng)建了,而且學號類的構造函數(shù)先于學生類對象的構造函數(shù)體的執(zhí)行而執(zhí)行。11/17/202219classStudentID{在學生類的構對于Students(“Randy”);其內部的執(zhí)行順序是這樣的:(1)先分配學生類對象s的空間,調用Student構造函數(shù);(2)在Student構造函數(shù)體尚未執(zhí)行時,由于看到了類的對象成員ID,轉而去調用學號類的無參構造函數(shù);相當于執(zhí)行定義語句:StudentIDid;(3)執(zhí)行了學號類構造函數(shù)體,輸出結果的第1行信息,返回到Student構造函數(shù);(4)執(zhí)行Student構造函數(shù)體,輸出結果的第2行信息,完成全部構造工作。說明:先成員構造,后自身構造.成員構造不見顯式調用,而是悄悄調用無參構造函數(shù).對學號類構造函數(shù)的調用時默認的,默認調用便是調用無參構造函數(shù),而正好學號類設計的構造函數(shù)就是無參構造函數(shù)。11/17/202220對于Students(“Randy”);其內部的執(zhí)行順序初始化的困惑在剛剛的實例中,只是初始化了名稱,而沒有給定學號。如果,在學生對象創(chuàng)建中,既要初始化名稱,又要給定一個指定的初始化學號,也就是不要默認調用無參構造函數(shù),那么類該如何操作呢?如果不能在創(chuàng)建StudentID的過程中初始化對象,就不能將對象值設置到位。下面給出一個不正確的初始化嘗試,還是對剛才的例子作修改:11/17/202221初始化的困惑在剛剛的實例中,只是初始化了名稱classStudentID{intvalue;public:
StudentID(intid=0){value=id;cout<<"Assigningstudentid"<<value<<"\n";}};//-----------------------------------classStudent{stringname;StudentIDid;public:Student(stringn="noName",intssID=0){cout<<"Constructingstudent"+n+"\n";name=n;
StudentIDid(ssID);}};//-----------------------------------intmain(){Students("Randy",58);}//====================================運行結果:11/17/202222classStudentID{運行結果:11/9/2022S對象初始化的學號為58,重新設計了Student構造函數(shù),將該值傳遞給了它,所以形參ssID的值也為58。但是我們看到轉而調用的StudentID構造函數(shù)執(zhí)行體卻沒有輸出58,而是默認的0學號。這說明轉而調用的仍然是無參構造函數(shù)。將StudentID的構造函數(shù)寫成參數(shù)默認是為了讓無參構造函數(shù)調用也能通過,以便讓整個程序順利運行。乃至后來,要想在Student類內,通過構造函數(shù)體中的對象初始化創(chuàng)建的定義語句來改變id的值,發(fā)現(xiàn)這僅僅只是區(qū)別于s對象中的id對象的一個局部對象,等到構造函數(shù)結束時,該局部對象的局部生命期到期而不銷毀。11/17/202223S對象初始化的學號為58,重新設計了St如果一個類A的對象作為另一個類B的數(shù)據(jù)成員,則在類B的對象創(chuàng)建過程中,調用其構造函數(shù)的過程中,數(shù)據(jù)成員(類A的對象)會自動調用類A的構造函數(shù)。
如果類A的構造函數(shù)為有參函數(shù)時,則在程序中必須在類B的構造函數(shù)的括號后面加一“:”和被調用的類A的構造函數(shù),且調用類A的構造函數(shù)時的實參值必須來自類B的形參表中的形參。這種方法稱為初始化表的方式調用構造函數(shù)。
這種在構造函數(shù)的參數(shù)列表的右括號后面,花括號前面,用冒號引出構造函數(shù)的調用表,可以省略類型名稱,但卻行創(chuàng)建對象之職。初始化表調用構造函數(shù)11/17/202224如果一個類A的對象作為另一個類B的數(shù)據(jù)成員,則類X的構造函數(shù)的定義格式應為:X::X(參數(shù)表0):成員1(參數(shù)表1),成員2(參數(shù)表2),…,成員n(參數(shù)表n){……}其中,參數(shù)表1提供初始化成員1所需的參數(shù),參數(shù)表2提供初始化成員2所需的參數(shù),依此類推。并且這幾個參數(shù)表的中的參數(shù)均來自參數(shù)表0,另外,初始化X的非對象成員所需的參數(shù),也由參數(shù)表0提供。在構造新類的對象過程中,系統(tǒng)首先調用其子對象的構造函數(shù),初始化子對象;然后才執(zhí)行類X自己的構造函數(shù),初始化類中的非對象成員。對于同一類中的不同子對象,系統(tǒng)按照它們在類中的說明順序調用相應的構造函數(shù)進行初始化,而不是按照初始化表的順序。11/17/202225類X的構造函數(shù)的定義格式應為:11/9/202例:#include<iostream>usingnamespacestd;//-------------------------------------classStudentID{intvalue;public:
StudentID(intid=0)//有參構造函數(shù){value=id;cout<<"Assigningstudentid"<<value<<endl;}};//-----------------------------------對剛才的例子進行改進11/17/202226例:#include<iostream>對剛才的例子進行改進classStudent{stringname;StudentIDid;public:Student(stringn="noname",intssID=0):id(ssID),name(n){cout<<"Constructingstudent"<<n<<"\n";}};//-----------------------------------intmain(){Students("Randy",98);Studentt("Jenny");}//==========================11/17/202227classStudent{11/9/202227
4.構造順序
在程序中,各種作用域的對象很多,有些對象還包含在別的對象里面,有些對象早在main函數(shù)開始運行之前就已經建立了。創(chuàng)建對象的惟一途徑是調用構造函數(shù)。構造函數(shù)時一段程序,所以構造對象的先后順序不同,直接影響程序執(zhí)行的先后順序,導致不同的運行結果。C++給構造對象的順序做了專門的規(guī)定。局部對象局部和靜態(tài)對象是指塊作用域(局部作用域)和文件作用域的對象。它們的聲明順序與它們在程序中出現(xiàn)的順序是一致的。見課本307頁例9.811/17/202228
4.構造順序
在程序中,各種作用域的對象在C中,所有的局部變量(沒有對象)都是在函數(shù)開始執(zhí)行時統(tǒng)一創(chuàng)建的,創(chuàng)建的順序是根據(jù)變量在程序中按語句行出現(xiàn)的順序。而C++卻不同,它是根據(jù)運行中定義對象的順序來決定對象創(chuàng)建的順序。而且,靜態(tài)對象只創(chuàng)建一次。全局對象和全局變量一樣,所有全局對象在主函數(shù)啟動之前,全部已近被構造。因為構造過程是程序語句的執(zhí)行過程,所以,可以想象在程序啟動之前,已經有程序語句(構造函數(shù))在那里被執(zhí)行過了。11/17/202229在C中,所有的局部變量(沒有對象)都是在函數(shù)開同一工程不同代碼文件全局對象的創(chuàng)建沒有明確順序規(guī)定.對策:不要讓不同文件的全局對象互為依賴.因為依賴具有先后性,而其全局對象的創(chuàng)建不能保證該依賴性發(fā)揮作用.全局對象在main函數(shù)啟動之前生成,而調試則在main函數(shù)啟動之后.對策:調試時,應先將全局對象作為局部對象來運行觀察.或者,在構造函數(shù)中添加輸出語句來觀察運行過程.11/17/202230同一工程不同代碼文件全局對象的創(chuàng)建沒有明確順序規(guī)定.11/9成員對象的構造順序按類定義的出現(xiàn)順序成員對象classA{public:A(intx){cout<<"A:"<<x<<"->";}};//-----------------------------------classB{public:B(intx){cout<<"B:"<<x<<"->";}};//-----------------------------------classC{Aa;Bb;public:C(intx,inty):b(x),a(y){cout<<"C\n";}};//-----------------------------------intmain(){Cc(15,9);}//============================classC按A、B的順序定義對象成員,其構造函數(shù)又按b、a的順序進行構造。到底聽誰的,以定義順序說了算。11/17/202231成員對象的構造順序按類定義的出現(xiàn)順序成員對象classA{構造位置全局數(shù)據(jù)區(qū):全局對象,靜態(tài)全局對象,靜態(tài)局部對象,常對象類的靜態(tài)數(shù)據(jù)成員也存放在該數(shù)據(jù)區(qū)。目的是為了讓對象的生命周期與運行的程序等壽命。棧區(qū):局部對象在函數(shù)中定義好、局部對象,隨著被調用的返回而析構(銷毀)。動態(tài)存儲區(qū)(也稱堆區(qū)):用new申請的對象用delete銷毀。特殊地址空間除此之外,還可以指定特殊地址空間,存放對象11/17/202232構造位置全局數(shù)據(jù)區(qū):11/9/202232回顧11/17/202233回顧11/9/202233
5.拷貝構造函數(shù)對象本體與對象實體:對象本體也是對象主體,對象實體則還包括屬于對象的衍生物,如,某個人體是人類對象的主體,然而某人還擁有父母,房產等屬于某人的世系或資產,描述人的屬性不僅僅只是人體數(shù)據(jù).從形式上看,對象除了包括數(shù)據(jù)成員,還包括指向數(shù)據(jù)的指針.對象本體與對象實體是不一致就是說有時我們會需要把a對象的屬性全部轉給b對象,
對象本體與對象實體一致就是你要將a對象的屬性賦給a對象本身。11/17/202234
5.拷貝構造函數(shù)對象本體與對象實體:11/9/20223對于一個簡單的變量的初始化方法是用一個常量或變量初始化另一個變量,例如:doublex=12.36;doubley=x;疑問:前面介紹了用構造函數(shù)初始化對象,那么能不能像簡單變量的初始化一樣,直接用一個對象來初始化另一個對象呢?答案是肯定的。例:以定義的一個Point類為例,說明用一個對象來初始化另一個對象。Pointpt1(10,20);Pointpt2=pt1;那么,后一句也可寫成Pointpt2(pt1);它是用pt1初始化pt2,此時,pt2各個成員的值與pt1各個成員的值相同,也就是說,pt1各個成員的值被復制到pt2相應的成員當中。在這個初始化過程當中,實際上調用了一個拷貝構造函數(shù)。11/17/202235對于一個簡單的變量的初始化方法是用一個常量或變量初始化另一個拷貝構造函數(shù):拷貝構造函數(shù)是C++中引入的一種新的構造函數(shù)。定義一個拷貝構造函數(shù)的方式是:類名(const類名&形式參數(shù)){函數(shù)體}由此可看出拷貝構造函數(shù)的特點:(1)拷貝構造函數(shù)的名稱與類的名稱相同,且它只有一個參數(shù),該參數(shù)就是對該類對象的引用。(2)拷貝構造函數(shù)的功能是用于實現(xiàn)對象值的拷貝,通過將一個同類對象的值拷貝給一個新對象,來完成對新對象的初始化,即用一個對象去構造另外一個對象。(3)每個類都有一個拷貝構造函數(shù)11/17/202236拷貝構造函數(shù):11/9/202236以本類對象為常量引用參數(shù)的構造函數(shù):classDate{public:Date();
Date(constDate&d);//...};Datex;//調用無參構造函數(shù)Datey(x);//調用拷貝構造函數(shù)例:11/17/202237以本類對象為常量引用參數(shù)的構造函數(shù):例:11/9/20223默認拷貝構造函數(shù):若類中沒有定義拷貝構造函數(shù),則系統(tǒng)會悄悄定義一個默認空拷貝構造函數(shù):Date(constDate&d){}默認拷貝構造函數(shù)體一定是空的.空拷貝構造函數(shù)負責將傳遞的對象到新創(chuàng)的對象做對象本體的位對位拷貝.(甚至連指針值都相等,即與參數(shù)對象擁有共同的資源)11/17/202238默認拷貝構造函數(shù):11/9/202238自定義拷貝構造函數(shù):為了達到對象實體也就是對象整體復制目的,就需要另外定義一個拷貝構造函數(shù),以覆蓋默認的拷貝構造函數(shù):見課本例315頁9.13自定義拷貝構造名也是類名,它是構造函數(shù)的重載,一旦自定義了拷貝構造函數(shù),默認的拷貝構造函數(shù)就不再起作用了。在自定義拷貝構造函數(shù)之前,我們進行拷貝對象構造時,都是在用默認的拷貝構造函數(shù),因為那時的對象本體與對象實體是一致的。所以,自定義拷貝構造函數(shù)在對象本體與對象實體不一致時,便是需要的,否則無此需要。11/17/202239自定義拷貝構造函數(shù):為了達到對象實體也就是對象自定義拷貝構造函數(shù)體的工作不負責位對位對象復制,一般來說,它負責資源分配和由此而來的指針修改.classPerson{
char*pName;public:Person(char*pN="noName"){pName=newchar[strlen(pN)+1];
if(pName)strcpy(pName,pN);}Person(constPerson&s){pName=newchar[strlen(s.pName)+1];
if(pName)strcpy(pName,s.pName);}~Person(){
delete[]pName;}};11/17/202240自定義拷貝構造函數(shù)體的工作不負責位對位對象復制,一般來說,它6.析構函數(shù)當一個對象被定義時,系統(tǒng)自動調用構造函數(shù)為該對象分配相應的資源,當對象使用完畢后,這些系統(tǒng)資源需要在對象消失前被釋放。人為的動態(tài)內存釋放工作由析構函數(shù)來完成,析構函數(shù)時一種特殊的成員函數(shù),它的意義是做關于對象失效之前瞬間的善后工作。它的功能與構造函數(shù)的工作正好相反,是用來釋放一個對象。我們知道有內存申請,也就有內存釋放。一般來說,需要定義構造函數(shù)的類也需要定義析構函數(shù),不需要構造函數(shù)的類,也無須定義析構函數(shù)。所以析構函數(shù)和構造函數(shù)是成對出現(xiàn)的。
11/17/2022416.析構函數(shù)當一個對象被定義時,系統(tǒng)自動調用析構函數(shù)的定義方式為:~類名(){函數(shù)體}定義:特點:(1)析構函數(shù)名與構造函數(shù)名相同,但它前面必須加一個“~”,用以與析構函數(shù)相區(qū)別;(2)在定義析構函數(shù)時,不能指定任何返回類型,也沒有參數(shù),而且不能重載。因此在一個類中只能有一個析構函數(shù)。(3)析構函數(shù)可以被用戶調用,也可以被系統(tǒng)調用。在下面兩種情況下,析構函數(shù)會被自動調用11/17/202242析構函數(shù)的定義方式為:定義:特點:11/9/202242a、如果一個對象被定義在一個函數(shù)體內,則當這個函數(shù)結束時,該對象的析構函數(shù)被自動調用。b、當一個對象是使用new運算符動態(tài)創(chuàng)建時的,在使用delete運算符自動釋放時,delete將會自動調用析構函數(shù)。每一個類若沒有顯示地定義為一個類定義析構函數(shù),編譯系統(tǒng)會自動地生成一個默認的析構函數(shù),默認析構函數(shù)時一個空函數(shù),實際上什么操作都不進行。例:程序中三個類A、B、C分別有一個析構函數(shù)。代碼如下:11/17/202243a、如果一個對象被定義在一個函數(shù)體內,則當這個函數(shù)結束時,該classA{public:A(){cout<<"A->";}~A(){cout<<"<-~A";}};//-------------------------classB{public:B(){cout<<"B->";}~B(){cout<<"<-~B";}};//-------------------------classC{public:C(){cout<<"C->";}~C(){cout<<"<-~C";}};//-------------------------voidfunc(){cout<<"\nfunc:";Aa;cout<<"ok->";staticBb;Cc;}//----------------------------intmain(){cout<<"main:";for(inti=1;i<=2;++i){for(intj=1;j<=2;++j)if(i==2)Cc;elseAa;Bb;}func();func();}//=================11/17/202244classA{voidfunc(){11/9/20224注:(1)析構函數(shù)總是出現(xiàn)在對象的生命期結束之時。靜態(tài)對象在程序運行結束時析構。(2)對于一個簡單的類來說,大多可以直接使用系統(tǒng)提供的默認析構函數(shù)。但是,如果在類的對象中分配有動態(tài)內存(如:用new申請分配的內容)時,就必須為該類提供適當?shù)奈鰳嫼瘮?shù),完成清理工作。(3)對象被析構的順序與對象建立時的順序正好相反。對象析構與構造函數(shù)的關系是棧數(shù)據(jù)結構中的入棧和出棧的關系,即最后構造的對象先被析構。棧底封閉指針11/17/202245注:棧底封閉指針11/9/2022457.對象轉型與賦值用于轉型的構造函數(shù)5/8與5.0/8的結果是不同的,原因是C++執(zhí)行了兩種不同的操作。編譯器會將5.0/8中的整數(shù)8自動轉換成double,匹配兩個double數(shù)的除法操作。這是內部數(shù)據(jù)類型所具有的轉換功能。但是,對于類類型,其自動轉換的功能必須編程實現(xiàn)。那就是定義一個含有一個參數(shù)的構造函數(shù)。例:classStudent{public:Student(conststring&n);};voidfn(Student&s);intmain(){stringt=“jenny”;fn(t);//參數(shù)為string,卻能匹配Student類型}11/17/2022467.對象轉型與賦值用于轉型的構造函數(shù)5/剛才的例子也是在告知,如何將string對象轉換成一個Student對象。如果有重載函數(shù):voidfn(string&s){cout<<“ok\n”;}則main函數(shù)中的fn(t)函數(shù)調用將會馬上匹配。否則,匹配了voidfn(Student&s)函數(shù)。從fn(Student&)和Student(conststring)可以推得fn(string)調用,這就是構造函數(shù)用來從一種類型轉換成另一種類型的能力。對象轉型的規(guī)則:只會嘗試含有一個參數(shù)的構造函數(shù)如果有二義性,則會放棄嘗試推導是一次性的,不允許多步推導11/17/202247剛才的例子也是在告知,如何將string對象對象拷貝對象賦值即對象拷貝:兩個已經存在的對象之間的復制Persond(“Ranny”)Persong;d=g;//對象賦值對象賦值便是使用類中的賦值操作符.如果類中沒有定義賦值操作符,則系統(tǒng)悄悄地定義一個默認的賦值操作符:Person&operator=(constPerson&p){memcpy(*this,*p,sizeof(p));}11/17/202248對象拷貝對象賦值即對象拷貝:兩個已經存在的對象之11/9/2當對象本體與對象實體不同時,則對象賦值操作符與拷貝構造函數(shù)一樣,必須自定義:classPerson{
char*pName;public:Person(char*pN="noName");Person(constPerson&s);Person&operator=(constPerson&s){
if(this==&s)returns;
delete[]pName;pName=newchar[strlen(s.pName)+1];
if(pName)strcpy(pName,s.pName);
return*this;}~Person(){delete[]pName;}};定義賦值操作符:1排除客體對象與本對象同一的情況2釋放本對象的資源3申請客體對象相同大小的資源空間4拷貝客體對象的資源到本對象11/17/202249當對象本體與對象實體不同時,則對象賦值操作符與拷貝構造函數(shù)一8.this指針用類定義對象時,系統(tǒng)會為每一個對象分配存儲空間。如果一個類包括數(shù)據(jù)和函數(shù),要分別為數(shù)據(jù)和函數(shù)的代碼分配存儲空間。每個對象所占用的存儲空間只是該對象的數(shù)據(jù)部分所占用的存儲空間,而不包括函數(shù)代碼所占用的存儲空間。例如:ClassPoint{intxVal,yVal;public:
point(intx,inty);point(point&pt);voidshowpoint(){cout<<“(“<<xVal<<‘,’<<yVal<<“)”;}}Pointa,b,c;11/17/2022508.this指針用類定義對象時,系統(tǒng)會為對象aintxValIntyVal對象bintxValIntyVal對象cintxValIntyVal成員函數(shù):Point(intx,inty);Point(Point&pt);voidShowPoint();對象存儲示意圖對象a、b、c在內存中各占8個字節(jié)存儲數(shù)據(jù)成員,而只用一段空間來存放這個共同的函數(shù)代碼段。疑問:當不同對象的成員函數(shù)引用數(shù)據(jù)成員時,怎么能保證引用的是所指定的對象的數(shù)據(jù)成員呢?11/17/202251對象aintxValIntyVal對象bintxV實際上在每一個成員函數(shù)中都包含一個特殊的指針,這個指針的名字是固定的,稱為this。它是指向本類對象的指針,它隱含在類的成員函數(shù)中,用來指向成員函數(shù)所述類的正在被操作的對象。例如,當調用成員函數(shù)a.ShowPoint()時,編譯系統(tǒng)就把對象a的起始地址付給this指針,于是在成員函數(shù)引用數(shù)據(jù)成員時,就按照this的指向找到對象a的數(shù)據(jù)成員,由于當前this指向a,因此相當于執(zhí)行cout<<“(“<<a.xVal<<“,”<<b.xVal<<“)”;歸納:(1)This指針也是一個指向對象的指針。(2)This指針是C++語言實現(xiàn)封裝的一種機制,它將數(shù)據(jù)成員和成員函數(shù)連接在一起,當一個成員函數(shù)對數(shù)據(jù)成員進行操作時,用this指針來表示數(shù)據(jù)成員所在的對象。(3)當程序操作不同對象的成員函數(shù)時,this指針也指向不同的對象(4)靜態(tài)成員函數(shù)沒有this指針。11/17/202252實際上在每一個成員函數(shù)中都包含一個特殊的指C++程序設計教程(第二版)第九章對象生滅11/17/202253C++程序設計教程(第二版)第九章對象生滅11/9/20第九章內容構造函數(shù)設計構造函數(shù)的重載類成員初始化構造順序拷貝構造函數(shù)析構函數(shù)對象轉型與賦值11/17/202254第九章內容構造函數(shù)設計11/9/202221.構造函數(shù)設計
初始化要求定義一個對象,其形式與定義一個變量相似,但更具意義。對象與變量的不同在于對象對應于事物,要求從誕生之時起便有明確的意義.對象必須建立一種初始化機制,以滿足在編程中可以針對實際問題所提出的要求而賦給一個有意義的初值。創(chuàng)建一個對象,若創(chuàng)建的是全局對象,則以全0的模式表示對象,若創(chuàng)建局部對象,則以隨機值表示對象。11/17/2022551.構造函數(shù)設計
初始化要求定義一個對象,對象的初始化不是簡單的參數(shù)與成員對應,而是聯(lián)系參數(shù)到成員的過程.封裝性要求StructPoint{intx,y;};Pointd={2,3};classPoint{intx,y;//…};Pointd={2,3};正確錯誤封裝性的要求杜絕了這種初始化形式,事實上,這種形式根本不能完成對象的初始化過程中的校驗和計算工作。對象通常是一個復雜的實體,在構建對象過程中,并不一定是一個初值對應一個對象分量。許多時候,一個初值只是傳遞一個信息,告訴對象的創(chuàng)建工作應怎么進行。封裝性要求對象創(chuàng)建中按傳遞的信息進行一個過程化的初始化工作。11/17/202256對象的初始化不是簡單的參數(shù)與成員對應,而是聯(lián)系函數(shù)形式構造函數(shù)(constructor)是與類名同名的特殊的成員函數(shù),當定義該類的對象時,構造函數(shù)將被自動調用以實現(xiàn)對該對象的初始化。構造函數(shù)不能有返回值,因而不能指定包括void在內的任何返回值類型。構造函數(shù)的定義體可與其它成員函數(shù)成員一樣,放在類內或類外都可。構造函數(shù)的定義格式為:類名(形參說明){函數(shù)體}構造函數(shù)既可定義成有參函數(shù),也可義成無參函數(shù),要根據(jù)問題的需要來定。全局變量和靜態(tài)變量在定義時,將自動賦初值為0;局部變量在定義時,其初始值不固定的。而當對象被定義時,由于對象的意義表達了現(xiàn)實世界的實體,所以一旦定義對象,就必須有一個有意義的初始值,在C++中,在定義對象的同時,給該對象初始化的方法就是利用構造函數(shù)。11/17/202257函數(shù)形式構造函數(shù)(constructor)是與類名同名的特殊例:類person包括4個數(shù)據(jù)成員,用來記錄人員信息。生成對象obj,并使用構造函數(shù)為obj賦予初始值。#include<windows.h>#include<iostream.h>classPerson //定義類{private: //類Person的數(shù)據(jù)成員charname[10]; //姓名intage; //年齡intsalary; //薪金chartel[8]; //電話public: //構造函數(shù)PersonPerson(char*xname,intxage,intxsalary,char*xtel);voiddisp();};//函數(shù)Person的定義Person::Person(char*xname,intxage,intxsalary,char*xtel){strcpy(name,xname);//給各數(shù)據(jù)成員提供初值age=xage;salary=xsalary;strcpy(tel,xtel);}11/17/202258例:類person包括4個數(shù)據(jù)成員,用來記錄人員//函數(shù)disp的定義voidPerson::disp(){cout<<endl;cout<<"姓名:"<<name<<endl;cout<<"年齡:"<<age<<endl;cout<<"工資:"<<salary<<endl;cout<<"電話:"<<tel<<endl<<endl;}//主函數(shù)voidmain(){//生成對象obj并初始化Personobj("張立三",25,850,"45672314");//顯示objobj.disp();}11/17/202259//函數(shù)disp的定義11/9/20227程序的執(zhí)行結果是:姓名:張立三年齡:25工資:850電話:45672314在主函數(shù)中的Personobj("張立三",25,850,"45672314");中完成了以下幾個功能:1.定義并生成了對象obj。2.在生成對象obj的同時,自動調用相應類的構造函數(shù)Person3.將初始值"張立三",25,850,"45672314"傳遞給構造函數(shù)Person相應的形參xname,xage,xsalary,xtel。4.執(zhí)行構造函數(shù)體,將相應的值賦給相應的數(shù)據(jù)成員。11/17/202260程序的執(zhí)行結果是:11/9/20228一次性對象創(chuàng)建對象時如果不給出對象名,直接以類名調用構造函數(shù),則產生一個無名對象。無名對象經常在參數(shù)傳遞時使用。例如:cout<<Date(2003,12,23);Date(2003,12,23)是一個對象,該對象在做了<<操作后便煙消云散了,所以這種對象一般用在創(chuàng)建后不需要反復使用的場合。11/17/202261一次性對象創(chuàng)建對象時如果不給出對象名,直接以
2.構造函數(shù)重載
構造函數(shù)畢竟是函數(shù),是函數(shù)就可以重載。不但可以重載,還可以設置默認參數(shù)。如果一個類中出現(xiàn)了兩個以上的同名的成員函數(shù)時,稱為類的成員函數(shù)的重載。classDate{public:Date(conststring&s);//重載Date(inty=2003,intm=12,intd=1);//參數(shù)默認//...};intmain(){Dated(“2006-12-26”);Datee(2000,12,25);Datef(2001,10);Dateg(2002);Dateh;//...}11/17/202262
2.構造函數(shù)重載
構造函數(shù)畢竟是函數(shù),是函Dateh;這行代碼似乎是一個錯誤,對于對象的創(chuàng)建,即對于無參的構造函數(shù)的調用,應該是g(),加上類名,即寫成:Dateg();但是,從語法上來講,這個語句也是名叫g的返回臨時Date對象的函數(shù)聲明!因此,C++語言在設計時,為了區(qū)別無初始化的對象定義和返回類對象的無參函數(shù)聲明的差別,也為了保持無初始化變量定義與無初始化(無參)對象定義的一致性,規(guī)定無參對象定義語句為:inta;//變量定義intb;//返回整型值的無參函數(shù)聲明Dateg;//無參對象定義,加空括號后就成了無參函數(shù)聲明Dateg();//返回類對象的無參函數(shù)聲明11/17/202263Dateh;這行代碼似乎是一個錯誤,對于對象的創(chuàng)建,即對對于返回對象值的有參函數(shù)聲明和有初始化的對象定義語句,由于函數(shù)聲明中的參數(shù)有類型引導,而對象定義的初始化中無類型引導,它們本身(或在編譯器看來)是可以區(qū)分的:Datee(2002);//對象定義Datee(inty);//函數(shù)聲明11/17/202264對于返回對象值的有參函數(shù)聲明和有初始化的對象C++規(guī)定,每個類必須有一個構造函數(shù)。如果在類中沒有顯式定義構造函數(shù)時,則C++編譯系統(tǒng)在編譯時為該類提供一個默認的構造函數(shù),該默認構造函數(shù)是個無參函數(shù),它僅負責創(chuàng)建對象,而不做任何初始化工作。classDate{public://相當于定義了Date(){}};intmain(){Dated;//ok//...}與變量定義相似,在用默認構造函數(shù)創(chuàng)建對象時,如果創(chuàng)建的是全局對象或靜態(tài)對象,則對象的默認值為0,否則對象的初始值是不定的。11/17/202265C++規(guī)定,每個類必須有一個構造函數(shù)。如果在類中沒有顯式定只要一個類定義了一個構造函數(shù)(不一定是無參構造函數(shù)),C++編譯系統(tǒng)就不再提供默認的構造函數(shù)。任何其他的構造函數(shù)定義,都將阻止默認無參空函數(shù)的產生:classDate{public:Date(inty,intm,intd){}//...};intmain(){Dated;//error//...}11/17/202266只要一個類定義了一個構造函數(shù)(不一定是無參構造函數(shù)),11/當構造函數(shù)有缺省參數(shù)時,稱為具有缺省參數(shù)的構造函數(shù),在使用時要防止二義性。如:classMyclass//定義類Myclass{private:intmember;public:Myclass();Myclass(inti);……}Myclass:Myclass()//構造函數(shù)Myclass{member=10;}11/17/202267當構造函數(shù)有缺省參數(shù)時,稱為具有缺省參數(shù)的構Myclass:Myclass(inti=10)//構造函數(shù)Myclass(inti),該函數(shù)//的形參i為缺省參數(shù){member=i;}voidmain(){Myclassx(20);Myclassy; //產生二義性,無法確定自動調用哪個構造//函數(shù)完成對象的構造……}11/17/202268Myclass:Myclass(inti=10)//構造回顧:上節(jié)課主要講了構造函數(shù)的概念、意義及定義方式、構造函數(shù)的重載。11/17/202269回顧:11/9/202217
3.類成員初始化
默認調用的無參構造函數(shù)在類定義中有數(shù)據(jù)成員和成員函數(shù),數(shù)據(jù)成員可以是內部數(shù)據(jù)類型的變量實體,也可以是對象實體。如果一個類A的對象作為另一個類B的數(shù)據(jù)成員,則在類B的對象創(chuàng)建過程中,調用其構造函數(shù)的過程中,數(shù)據(jù)成員(類A的對象)會自動調用類A的構造函數(shù)。這樣就會面臨一些問題。例:有一個學號類和一個學生類,學生類中包含了學號類的對象,因此在構造學生類對象時,面臨著學號類對象的構造。11/17/202270
3.類成員初始化
默認調用的無參構造函數(shù)classStudentID{intvalue;public:
StudentID(){staticintnextStudentID=0;value=++nextStudentID;cout<<"Assigningstudentid"<<value<<"\n";}};//-----------------------------------classStudent{stringname;
StudentIDid;public:Student(stringn="noName"){cout<<"Constructingstudent"+n+"\n";name=n;}};//-----------------------------------intmain(){Students("Randy");}//==============================在學生類的構造函數(shù)中并沒有看到學號類對象初始化的痕跡,而數(shù)據(jù)成員name倒被賦了初值。從運行的結果看,當學生類對象被構造時,一個學號對象也創(chuàng)建了,而且學號類的構造函數(shù)先于學生類對象的構造函數(shù)體的執(zhí)行而執(zhí)行。11/17/202271classStudentID{在學生類的構對于Students(“Randy”);其內部的執(zhí)行順序是這樣的:(1)先分配學生類對象s的空間,調用Student構造函數(shù);(2)在Student構造函數(shù)體尚未執(zhí)行時,由于看到了類的對象成員ID,轉而去調用學號類的無參構造函數(shù);相當于執(zhí)行定義語句:StudentIDid;(3)執(zhí)行了學號類構造函數(shù)體,輸出結果的第1行信息,返回到Student構造函數(shù);(4)執(zhí)行Student構造函數(shù)體,輸出結果的第2行信息,完成全部構造工作。說明:先成員構造,后自身構造.成員構造不見顯式調用,而是悄悄調用無參構造函數(shù).對學號類構造函數(shù)的調用時默認的,默認調用便是調用無參構造函數(shù),而正好學號類設計的構造函數(shù)就是無參構造函數(shù)。11/17/202272對于Students(“Randy”);其內部的執(zhí)行順序初始化的困惑在剛剛的實例中,只是初始化了名稱,而沒有給定學號。如果,在學生對象創(chuàng)建中,既要初始化名稱,又要給定一個指定的初始化學號,也就是不要默認調用無參構造函數(shù),那么類該如何操作呢?如果不能在創(chuàng)建StudentID的過程中初始化對象,就不能將對象值設置到位。下面給出一個不正確的初始化嘗試,還是對剛才的例子作修改:11/17/202273初始化的困惑在剛剛的實例中,只是初始化了名稱classStudentID{intvalue;public:
StudentID(intid=0){value=id;cout<<"Assigningstudentid"<<value<<"\n";}};//-----------------------------------classStudent{stringname;StudentIDid;public:Student(stringn="noName",intssID=0){cout<<"Constructingstudent"+n+"\n";name=n;
StudentIDid(ssID);}};//-----------------------------------intmain(){Students("Randy",58);}//====================================運行結果:11/17/202274classStudentID{運行結果:11/9/2022S對象初始化的學號為58,重新設計了Student構造函數(shù),將該值傳遞給了它,所以形參ssID的值也為58。但是我們看到轉而調用的StudentID構造函數(shù)執(zhí)行體卻沒有輸出58,而是默認的0學號。這說明轉而調用的仍然是無參構造函數(shù)。將StudentID的構造函數(shù)寫成參數(shù)默認是為了讓無參構造函數(shù)調用也能通過,以便讓整個程序順利運行。乃至后來,要想在Student類內,通過構造函數(shù)體中的對象初始化創(chuàng)建的定義語句來改變id的值,發(fā)現(xiàn)這僅僅只是區(qū)別于s對象中的id對象的一個局部對象,等到構造函數(shù)結束時,該局部對象的局部生命期到期而不銷毀。11/17/202275S對象初始化的學號為58,重新設計了St如果一個類A的對象作為另一個類B的數(shù)據(jù)成員,則在類B的對象創(chuàng)建過程中,調用其構造函數(shù)的過程中,數(shù)據(jù)成員(類A的對象)會自動調用類A的構造函數(shù)。
如果類A的構造函數(shù)為有參函數(shù)時,則在程序中必須在類B的構造函數(shù)的括號后面加一“:”和被調用的類A的構造函數(shù),且調用類A的構造函數(shù)時的實參值必須來自類B的形參表中的形參。這種方法稱為初始化表的方式調用構造函數(shù)。
這種在構造函數(shù)的參數(shù)列表的右括號后面,花括號前面,用冒號引出構造函數(shù)的調用表,可以省略類型名稱,但卻行創(chuàng)建對象之職。初始化表調用構造函數(shù)11/17/202276如果一個類A的對象作為另一個類B的數(shù)據(jù)成員,則類X的構造函數(shù)的定義格式應為:X::X(參數(shù)表0):成員1(參數(shù)表1),成員2(參數(shù)表2),…,成員n(參數(shù)表n){……}其中,參數(shù)表1提供初始化成員1所需的參數(shù),參數(shù)表2提供初始化成員2所需的參數(shù),依此類推。并且這幾個參數(shù)表的中的參數(shù)均來自參數(shù)表0,另外,初始化X的非對象成員所需的參數(shù),也由參數(shù)表0提供。在構造新類的對象過程中,系統(tǒng)首先調用其子對象的構造函數(shù),初始化子對象;然后才執(zhí)行類X自己的構造函數(shù),初始化類中的非對象成員。對于同一類中的不同子對象,系統(tǒng)按照它們在類中的說明順序調用相應的構造函數(shù)進行初始化,而不是按照初始化表的順序。11/17/202277類X的構造函數(shù)的定義格式應為:11/9/202例:#include<iostream>usingnamespacestd;//-------------------------------------classStudentID{intvalue;public:
StudentID(intid=0)//有參構造函數(shù){value=id;cout<<"Assigningstudentid"<<value<<endl;}};//-----------------------------------對剛才的例子進行改進11/17/202278例:#include<iostream>對剛才的例子進行改進classStudent{stringname;StudentIDid;public:Student(stringn="noname",intssID=0):id(ssID),name(n){cout<<"Constructingstudent"<<n<<"\n";}};//-----------------------------------intmain(){Students("Randy",98);Studentt("Jenny");}//==========================11/17/202279classStudent{11/9/202227
4.構造順序
在程序中,各種作用域的對象很多,有些對象還包含在別的對象里面,有些對象早在main函數(shù)開始運行之前就已經建立了。創(chuàng)建對象的惟一途徑是調用構造函數(shù)。構造函數(shù)時一段程序,所以構造對象的先后順序不同,直接影響程序執(zhí)行的先后順序,導致不同的運行結果。C++給構造對象的順序做了專門的規(guī)定。局部對象局部和靜態(tài)對象是指塊作用域(局部作用域)和文件作用域的對象。它們的聲明順序與它們在程序中出現(xiàn)的順序是一致的。見課本307頁例9.811/17/202280
4.構造順序
在程序中,各種作用域的對象在C中,所有的局部變量(沒有對象)都是在函數(shù)開始執(zhí)行時統(tǒng)一創(chuàng)建的,創(chuàng)建的順序是根據(jù)變量在程序中按語句行出現(xiàn)的順序。而C++卻不同,它是根據(jù)運行中定義對象的順序來決定對象創(chuàng)建的順序。而且,靜態(tài)對象只創(chuàng)建一次。全局對象和全局變量一樣,所有全局對象在主函數(shù)啟動之前,全部已近被構造。因為構造過程是程序語句的執(zhí)行過程,所以,可以想象在程序啟動之前,已經有程序語句(構造函數(shù))在那里被執(zhí)行過了。11/17/202281在C中,所有的局部變量(沒有對象)都是在函數(shù)開同一工程不同代碼文件全局對象的創(chuàng)建沒有明確順序規(guī)定.對策:不要讓不同文件的全局對象互為依賴.因為依賴具有先后性,而其全局對象的創(chuàng)建不能保證該依賴性發(fā)揮作用.全局對象在main函數(shù)啟動之前生成,而調試則在main函數(shù)啟動之后.對策:調試時,應先將全局對象作為局部對象來運行觀察.或者,在構造函數(shù)中添加輸出語句來觀察運行過程.11/17/202282同一工程不同代碼文件全局對象的創(chuàng)建沒有明確順序規(guī)定.11/9成員對象的構造順序按類定義的出現(xiàn)順序成員對象classA{public:A(intx){cout<<"A:"<<x<<"->";}};//-----------------------------------classB{public:B(intx){cout<<"B:"<<x<<"->";}};//-----------------------------------classC{Aa;Bb;public:C(intx,inty):b(x),a(y){cout<<"C\n";}};//-----------------------------------intmain(){Cc(15,9);}//============================classC按A、B的順序定義對象成員,其構造函數(shù)又按b、a的順序進行構造。到底聽誰的,以定義順序說了算。11/17/202283成員對象的構造順序按類定義的出現(xiàn)順序成員對象classA{構造位置全局數(shù)據(jù)區(qū):全局對象,靜態(tài)全局對象,靜態(tài)局部對象,常對象類的靜態(tài)數(shù)據(jù)成員也存放在該數(shù)據(jù)區(qū)。目的是為了讓對象的生命周期與運行的程序等壽命。棧區(qū):局部對象在函數(shù)中定義好、局部對象,隨著被調用的返回而析構(銷毀)。動態(tài)存儲區(qū)(也稱堆區(qū)):用new申請的對象用delete銷毀。特殊地址空間除此之外,還可以指定特殊地址空間,存放對象11/17/202284構造位置全局數(shù)據(jù)區(qū):11/9/202232回顧11/17/202285回顧11/9/202233
5.拷貝構造函數(shù)對象本體與對象實體:對象本體也是對象主體,對象實體則還包括屬于對象的衍生物,如,某個人體是人類對象的主體,然而某人還擁有父母,房產等屬于某人的世系或資產,描述人的屬性不僅僅只是人體數(shù)據(jù).從形式上看,對象除了包括數(shù)據(jù)成員,還包括指向數(shù)據(jù)的指針.對象本體與對象實體是不一致就是說有時我們會需要把a對象的屬性全部轉給b對象,
對象本體與對象實體一致就是你要將a對象的屬性賦給a對象本身。11/17/202286
5.拷貝構造函數(shù)對象本體與對象實體:11/9/20223對于一個簡單的變量的初始化方法是用一個常量或變量初始化另一個變量,例如:doublex=12.36;doubley=x;疑問:前面介紹了用構造函數(shù)初始化對象,那么能不能像簡單變量的初始化一樣,直接用一個對象來初始化另一個對象呢?答案是肯定的。例:以定義的一個Point類為例,說明用一個對象來初始化另一個對象。Pointpt1(10,20);Pointpt2=pt1;那么,后一句也可寫成Pointpt2(pt1);它是用pt1初始化pt2,此時,pt2各個成員的值與pt1各個成員的值相同,也就是說,pt1各個成員的值被復制到pt2相應的成員當中。在這個初始化過程當中,實際上調用了一個拷貝構造函數(shù)。11/17/202287對于一個簡單的變量的初始化方法是用一個常量或變量初始化另一個拷貝構造函數(shù):拷貝構造函數(shù)是C++中引入的一種新的構造函數(shù)。定義一個拷貝構造函數(shù)的方式是:類名(const類名&形式參數(shù)){函數(shù)體}由此可看出拷貝構造函數(shù)的特點:(1)拷貝構造函數(shù)的名稱與類的名稱相同,且它只有一個參數(shù),該參數(shù)就是對該類對象的引用。(2)拷貝構造函數(shù)的功能是用于實現(xiàn)對象值的拷貝,通過將一個同類對象的值拷貝給一個新對象,來完成對新對象的初始化,即用一個對象去構造另外一個對象。(3)每個類都有一個拷貝構造函數(shù)11/17/202288拷貝構造函數(shù):11/9/202236以本類對象為常量引用參數(shù)的構造函數(shù):classDate{public:Date();
Date(const
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年全球及中國高效微粒空氣過濾器行業(yè)頭部企業(yè)市場占有率及排名調研報告
- 2024年拉絲工職業(yè)技能競賽理論考試題庫(含答案)
- 2025年度個人發(fā)明專利獨占許可合同范本3篇
- 2025年度個人旅游定制服務合同19篇
- 《財政與金融(第2版)》 課件 第十三章國際金融
- 二零二五年度打磨工勞動爭議調解合同3篇
- 現(xiàn)代學校安全管理技術探討
- 池州安徽池州石臺縣消防救援大隊招聘3人筆試歷年參考題庫附帶答案詳解
- 曲靖云南曲靖富源縣公安局交通警察大隊指揮中心招聘警務輔助人員筆試歷年參考題庫附帶答案詳解
- 2025年滬教版選擇性必修1物理下冊階段測試試卷
- 2024年安全教育培訓試題附完整答案(奪冠系列)
- 神農架研學課程設計
- 文化資本與民族認同建構-洞察分析
- 2025新譯林版英語七年級下單詞默寫表
- 【超星學習通】馬克思主義基本原理(南開大學)爾雅章節(jié)測試網課答案
- 《錫膏培訓教材》課件
- 斷絕父子關系協(xié)議書
- 福建省公路水運工程試驗檢測費用參考指標
- 2024年中國工業(yè)涂料行業(yè)發(fā)展現(xiàn)狀、市場前景、投資方向分析報告(智研咨詢發(fā)布)
- 自然科學基礎(小學教育專業(yè))全套教學課件
- 《工程勘察資質分級標準和工程設計資質分級標準》
評論
0/150
提交評論