版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
C++程序設(shè)計(jì)教程(第二版)9/19/20231第九章 對(duì)象生滅第九章內(nèi)容9/19/20232構(gòu)造函數(shù)設(shè)計(jì)構(gòu)造函數(shù)的重載類成員初始化構(gòu)造順序拷貝構(gòu)造函數(shù)析構(gòu)函數(shù)對(duì)象轉(zhuǎn)型與賦值1.構(gòu)造函數(shù)設(shè)計(jì)9/19/20233
初始化要求定義一個(gè)對(duì)象,其形式與定義一個(gè)變量相似,但更具意義。對(duì)象與變量的不同在于對(duì)象對(duì)應(yīng)于事物,要求從誕生之時(shí)起便有明確的意義.對(duì)象必須建立一種初始化機(jī)制,以滿足在編程中可以針對(duì)實(shí)際問題所提出的要求而賦給一個(gè)有意義的初值。創(chuàng)建一個(gè)對(duì)象,若創(chuàng)建的是全局對(duì)象,則以全0的模式表示對(duì)象,若創(chuàng)建局部對(duì)象,則以隨機(jī)值表示對(duì)象。對(duì)象的初始化不是簡單的參數(shù)與成員對(duì)應(yīng),而是聯(lián)系參數(shù)到成員的過程.封裝性要求Struct
Point{int
x,y;};Point
d={2,3};class
Point{int
x,y;//…};Point
d={2,3};正確錯(cuò)誤封裝性的要求杜絕了這種初始化形式,事實(shí)上,這種形式根本不能完成對(duì)象的初始化過程中的校驗(yàn)和計(jì)算工作。對(duì)象通常是一個(gè)復(fù)雜的實(shí)體,在構(gòu)建對(duì)象過程中,并不一定是一個(gè)初值對(duì)應(yīng)一個(gè)對(duì)象分量。許多時(shí)候,一個(gè)初值只是傳遞一個(gè)信息,告訴對(duì)象的創(chuàng)建工作應(yīng)怎么進(jìn)行。封裝性要求對(duì)象創(chuàng)建中按傳遞的信息進(jìn)10/行1/20一23
個(gè)過程化的初始化工作。4
函數(shù)形式構(gòu)造函數(shù)(constructor)是與類名同名的特殊的成員函數(shù),當(dāng)定義該類的對(duì)象時(shí),構(gòu)造函數(shù)將被自動(dòng)調(diào)用以實(shí)現(xiàn)對(duì)該對(duì)象的初始化。構(gòu)造函數(shù)不能有返回值,因而不能指定包括void在內(nèi)的任何返回值類型。構(gòu)造函數(shù)的定義體可與其它成員函數(shù)成員一樣,放在類內(nèi)或類外都可。構(gòu)造函數(shù)的定義格式為:類名(形參說明){函數(shù)體}構(gòu)造函數(shù)既可定義成有參函數(shù),也可義成無參函數(shù),要根據(jù)問題的需要來定。全局變量和靜態(tài)變量在定義時(shí),將自動(dòng)賦初值為0;局部變量在定義時(shí),其初始值不固定的。而當(dāng)對(duì)象被定義時(shí),由于對(duì)象的意義表達(dá)了現(xiàn)實(shí)世界的實(shí)體,所以一旦定義對(duì)象,就必須有一個(gè)有意義的初始值,在C++中,在定義對(duì)象的同時(shí),給該對(duì)象初始化的方法就是利用構(gòu)造函數(shù)。10/1/20235例:類person包括4個(gè)數(shù)據(jù)成員,用來記錄人員信息。生成對(duì)象obj,并使用構(gòu)造函數(shù)為obj賦予初始值。#
include<windows.h>#
include<iostream.h>class
Person{
private:char
name
[10]
;int
age
;int
salary
;chartel[8];public://定義類//類Person的數(shù)據(jù)成員//姓名//年齡//薪金//電話//構(gòu)造函數(shù)PersonPerson
(
char
*xname,
int
xage,int
xsalary,
char
*xtel
)
;void
disp
();
};//函數(shù)Person的定義Person
::
Person
(
char
*xname,int
xage,
int
xsalary,
char
*xtel
){strcpy
(name,xname);//給各數(shù)據(jù)成員提供初值
age=xage;salary
=
xsalary
;10/1s/t2r0c2p3y
(tel,
xtel)
;}6//函數(shù)disp的定義
void
Person::disp(){
cout<<endl;10/1/20237姓名:"<<name<<endl;年齡:"<<age<<endl;
工資:"<<salary<<endl;電話:"<<tel<<endl<<endl;}cout
<<
"cout
<<
"cout
<<
"cout
<<
"http://主函數(shù)void
main(
){
//生成對(duì)象obj并初始化Person obj("張立三",25,850,"45672314");//顯示objobj.disp();}程序的執(zhí)行結(jié)果是:姓名:張立三年齡:25工資:850電話:45672314在主函數(shù)中的Person
obj("張立三",25,850,"45672314");中完成了以下幾個(gè)功能:定義并生成了對(duì)象obj。在生成對(duì)象obj的同時(shí),自動(dòng)調(diào)用相應(yīng)類的構(gòu)造函數(shù)Person將初始值"張立三",25,850,"45672314"傳遞給構(gòu)造函數(shù)Person相應(yīng)的形參xname,xage,xsalary,
xtel。執(zhí)行構(gòu)造函數(shù)體,將相應(yīng)的值賦給相應(yīng)的數(shù)據(jù)成員。10/1/20238
一次性對(duì)象10/1/20239創(chuàng)建對(duì)象時(shí)如果不給出對(duì)象名,直接以類名調(diào)用構(gòu)造函數(shù),則產(chǎn)生一個(gè)無名對(duì)象。無名對(duì)象經(jīng)常在參數(shù)傳遞時(shí)使用。例如:cout<<Date(2003,12,23);Date(2003,12,23)是一個(gè)對(duì)象,該對(duì)象在做了<<操作后便煙消云散了,所以這種對(duì)象一般用在創(chuàng)建后不需要反復(fù)使用的場(chǎng)合。2.構(gòu)造函數(shù)重載10/1/202310class
Date{public:Date(const
string&
s);//重載//
...};構(gòu)造函數(shù)畢竟是函數(shù),是函數(shù)就可以重載。不但可以重載,還可以設(shè)置默認(rèn)參數(shù)。如果一個(gè)類中出現(xiàn)了兩個(gè)以上的同名的成員函數(shù)時(shí),稱為類的成員函數(shù)的重載。intmain(){Date
d(“2006-12-26”);Date
e(2000,
12,
25);Date
f(2001,
10);Date(int
y=2003,
int
m=12,
int
d=1);//參數(shù)默認(rèn)Dateg(2002);Date
h;//
...}Date
h;這行代碼似乎是一個(gè)錯(cuò)誤,對(duì)于對(duì)象的創(chuàng)建,即對(duì)于無參的構(gòu)造函數(shù)的調(diào)用,應(yīng)該是g(),加上類名,即寫成:
Dateg();但是,從語法上來講,這個(gè)語句也是名叫g(shù)的返回臨時(shí)Date對(duì)象的函數(shù)聲明!因此,C++語言在設(shè)計(jì)時(shí),為了區(qū)別無初始化的對(duì)象定義和返回類對(duì)象的無參函數(shù)聲明的差別,也為了保持無初始化變量定義與無初始化(無參)對(duì)象定義的一致性,規(guī)定無參對(duì)象定義語句為:10/1/202311int
a;int
b;Date
g;Dateg();//變量定義//返回整型值的無參函數(shù)聲明//無參對(duì)象定義,加空括號(hào)后就成了無參函數(shù)聲明//返回類對(duì)象的無參函數(shù)聲明對(duì)于返回對(duì)象值的有參函數(shù)聲明和有初始化的對(duì)象定義語句,由于函數(shù)聲明中的參數(shù)有類型引導(dǎo),而對(duì)象定義的初始化中無類型引導(dǎo),它們本身(或在編譯器看來)是可以區(qū)分的:10/1/202312Date
e(2002);Date e(int
y);//對(duì)象定義//函數(shù)聲明C++規(guī)定,每個(gè)類必須有一個(gè)構(gòu)造函數(shù)。如果在類中沒有顯式定義構(gòu)造函數(shù)時(shí),則C++編譯系統(tǒng)在編譯時(shí)為該類提供一個(gè)默認(rèn)的構(gòu)造函數(shù),該默認(rèn)構(gòu)造函數(shù)是個(gè)無參函數(shù),它僅負(fù)責(zé)創(chuàng)建對(duì)象,而不做任何初始化工作。class
Date{public://相當(dāng)于定義了Date(){}};intmain(){Date
d;
//
ok//
...}與變量定義相似,在用默認(rèn)構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí),如果創(chuàng)建的是全局對(duì)象或靜態(tài)對(duì)象,則對(duì)象的默認(rèn)值為0,否則對(duì)象的初始值是不定的。10/1/202313只要一個(gè)類定義了一個(gè)構(gòu)造函數(shù)(不一定是無參構(gòu)造函數(shù)),C++編譯系統(tǒng)就不再提供默認(rèn)的構(gòu)造函數(shù)。任何其他的構(gòu)造函數(shù)定義,都將阻止默認(rèn)無參空函數(shù)的產(chǎn)生:class
Date{public:Date(int
y,
int
m,
int
d){}//
...};int
main(){Date
d;
//
error//
...}10/1/202314當(dāng)構(gòu)造函數(shù)有缺省參數(shù)時(shí),稱為具有缺省參數(shù)的構(gòu)造函數(shù),在使用時(shí)要防止二義性。10/1/202315//定義類Myclass//構(gòu)造函數(shù)Myclass如:class
Myclass{
private:intmember;public:Myclass();Myclass(int
i);……}Myclass:Myclass(){
member=10;
}Myclass:Myclass(int
i=10)//構(gòu)造函數(shù)Myclass(int
i),該函數(shù)//的形參i為缺省參數(shù){
member=i;
}void
main(){
Myclass
x(20);10/1/202316Myclass
y;//產(chǎn)生二義性,無法確定自動(dòng)調(diào)用哪個(gè)構(gòu)造//函數(shù)完成對(duì)象的構(gòu)造……}回顧:上節(jié)課主要講了構(gòu)造函數(shù)的概念、意義及定義方式、構(gòu)造函數(shù)的重載。10/1/2023173.類成員初始化10/1/202318
默認(rèn)調(diào)用的無參構(gòu)造函數(shù)在類定義中有數(shù)據(jù)成員和成員函數(shù),數(shù)據(jù)成員可以是內(nèi)部數(shù)據(jù)類型的變量實(shí)體,也可以是對(duì)象實(shí)體。如果一個(gè)類A的對(duì)象作為另一個(gè)類B的數(shù)據(jù)成員,則在類B的對(duì)象創(chuàng)建過程中,調(diào)用其構(gòu)造函數(shù)的過程中,數(shù)據(jù)成員(類A的對(duì)象)會(huì)自動(dòng)調(diào)用類A的構(gòu)造函數(shù)。這樣就會(huì)面臨一些問題。例:有一個(gè)學(xué)號(hào)類和一個(gè)學(xué)生類,學(xué)生類中包含了學(xué)號(hào)類的對(duì)象,因此在構(gòu)造學(xué)生類對(duì)象時(shí),面臨著學(xué)號(hào)類對(duì)象的構(gòu)造。class
StudentID{int
value;
public:StudentID(){在學(xué)生類的構(gòu)造函數(shù)中并沒有看到學(xué)號(hào)類對(duì)象初始化的痕跡,而數(shù)據(jù)成員name倒被賦了初值。從運(yùn)行的結(jié)果看,當(dāng)學(xué)生類對(duì)象被構(gòu)造時(shí),一個(gè)學(xué)號(hào)對(duì)象也創(chuàng)建了,而且學(xué)號(hào)類的構(gòu)造函數(shù)先于學(xué)生類對(duì)象的構(gòu)造函數(shù)體的執(zhí)行而執(zhí)行。static
int
nextStudentID
=
0;value
=
++nextStudentID;cout<<"Assigning
student
id"<<value<<"\n";}};//-----------------------------------class
Student{string
name;StudentID
id;public:Student(string
n
=
"noName"){cout
<<"Constructing
student
"
+
n
+
"\n";name
=
n;}};//-----------------------------------int
main(){S1tu0/d1/2e0n23t
s("Randy");}//==============================19對(duì)于Student
s(“Randy”);其內(nèi)部的執(zhí)行順序是這樣的:先分配學(xué)生類對(duì)象s的空間,調(diào)用Student構(gòu)造函數(shù);在Student構(gòu)造函數(shù)體尚未執(zhí)行時(shí),由于看到了類的對(duì)象成員ID,轉(zhuǎn)而去調(diào)用學(xué)號(hào)類的無參構(gòu)造函數(shù);相當(dāng)于執(zhí)行定義語句:StudentID
id;執(zhí)行了學(xué)號(hào)類構(gòu)造函數(shù)體,輸出結(jié)果的第1行信息,返回到Student構(gòu)造函數(shù);執(zhí)行Student構(gòu)造函數(shù)體,輸出結(jié)果的第2行信息,完成全部構(gòu)造工作。說明:先成員構(gòu)造,后自身構(gòu)造.成員構(gòu)造不見顯式調(diào)用,而是悄悄調(diào)用無參構(gòu)造函數(shù).對(duì)學(xué)號(hào)類構(gòu)造函數(shù)的調(diào)用時(shí)
默認(rèn)的,默認(rèn)調(diào)用便是調(diào)用無參構(gòu)造函數(shù),而正好學(xué)號(hào)類
設(shè)計(jì)的構(gòu)造函數(shù)就是無參構(gòu)造函數(shù)。10/1/202320
初始化的困惑在剛剛的實(shí)例中,只是初始化了名稱,而沒有給定學(xué)號(hào)。如果,在學(xué)生對(duì)象創(chuàng)建中,既要初始化名稱,又要給定一個(gè)指定的初始化學(xué)號(hào),也就是不要默認(rèn)調(diào)用無參構(gòu)造函數(shù),那么類該如何操作呢?如果不能在創(chuàng)建StudentID的過程中初始化對(duì)象,就不能將對(duì)象值設(shè)置到位。下面給出一個(gè)不正確的初始化嘗試,還是對(duì)剛才的例子作修改:10/1/202321class
StudentID{intvalue;public:StudentID(int
id=0){value
=
id;cout<<"Assigning
student
id
"<<value<<"\n";}};//class
Student{string
name;StudentID
id;public:Student(string
n
=
"noName",
int
ssID=0){cout
<<"Constructing
student
"
+
n
+"\n";name
=
n;StudentID
id(ssID);}};//運(yùn)行結(jié)果:intmain(){Student
s("Randy",58);10/1/2}0/2/3====================================22S對(duì)象初始化的學(xué)號(hào)為58,重新設(shè)計(jì)了Student構(gòu)造函
數(shù),將該值傳遞給了它,所以形參ssID的值也為58。但是我們看到轉(zhuǎn)而調(diào)用的StudentID構(gòu)造函數(shù)執(zhí)行體卻沒有輸出58,而是默認(rèn)的0學(xué)號(hào)。這說明轉(zhuǎn)而調(diào)用的仍然是無參構(gòu)造函數(shù)。將StudentID的構(gòu)造函數(shù)寫成參數(shù)默認(rèn)是為了讓無參構(gòu)造函
數(shù)調(diào)用也能通過,以便讓整個(gè)程序順利運(yùn)行。乃至后來,要想在Student類內(nèi),通過構(gòu)造函數(shù)體中的對(duì)象初始化創(chuàng)建的定義語句來改變id的值,發(fā)現(xiàn)這僅僅只是區(qū)別于s對(duì)象中的id對(duì)象的一個(gè)局部對(duì)象,等到構(gòu)造函數(shù)結(jié)束時(shí),該局部對(duì)象的局部生命期到期而不銷毀。10/1/202323
初始化表調(diào)用構(gòu)造函數(shù)如果一個(gè)類A的對(duì)象作為另一個(gè)類B的數(shù)據(jù)成員,則在類B的對(duì)象創(chuàng)建過程中,調(diào)用其構(gòu)造函數(shù)的過程中,數(shù)據(jù)成員(類A的對(duì)象)會(huì)自動(dòng)調(diào)用類A的構(gòu)造函數(shù)。如果類A的構(gòu)造函數(shù)為有參函數(shù)時(shí),則在程序中必須在類B的構(gòu)造函數(shù)的括號(hào)后面加一“:”和被調(diào)用的類A的構(gòu)造函數(shù),且調(diào)用類A的構(gòu)造函數(shù)時(shí)的實(shí)參值必須來自類B的形參表中的形參。這種方法稱為初始化表的方式調(diào)用構(gòu)造函數(shù)。這種在構(gòu)造函數(shù)的參數(shù)列表的右括號(hào)后面,花括號(hào)前面,用冒號(hào)引出構(gòu)造函數(shù)的調(diào)用表,可以省略類型名稱,但卻行創(chuàng)建對(duì)象之職。10/1/202324類X的構(gòu)造函數(shù)的定義格式應(yīng)為:
X::X(參數(shù)表0):成員1(參數(shù)表1),成員2(參數(shù)表
2),…,成員n(參數(shù)表n){
……}其中,參數(shù)表1提供初始化成員1所需的參數(shù),參數(shù)表2提供初始化成員2所需的參數(shù),依此類推。并且這幾個(gè)參數(shù)表的中的參數(shù)均來自參數(shù)表0,另外,初始化X的非對(duì)象成員所需的參數(shù),也由參數(shù)表0提供。在構(gòu)造新類的對(duì)象過程中,系統(tǒng)首先調(diào)用其子對(duì)象的構(gòu)造函數(shù),初始化子對(duì)象;然后才執(zhí)行類X自己的構(gòu)造函數(shù),初始化類中的非對(duì)象成員。對(duì)于同一類中的不同子對(duì)象,系統(tǒng)按照它們?cè)陬愔械恼f明順序調(diào)用相應(yīng)的構(gòu)造函數(shù)進(jìn)行初始化,而不是按照初始化表的順序。10/1/202325例:#include<iostream>using
namespacestd;//class
StudentID{intvalue;public:StudentID(int
id=0)//有參構(gòu)造函數(shù){value=id;cout
<<"Assigning
student
id
"
<<value
<<endl;}};//對(duì)剛才的例子進(jìn)行改進(jìn)10/1/202326class
Student{string
name;StudentID
id;public:Student(string
n="no
name",
int
ssID=0):id(ssID),name(n){cout<<"Constructing
student
"<<n<<"\n";}};//intmain(){Student
s("Randy",98);Student
t("Jenny");}//==========================10/1/2023274.構(gòu)造順序10/1/202328在程序中,各種作用域的對(duì)象很多,有些對(duì)象還包含在別的對(duì)象里面,有些對(duì)象早在main函數(shù)開始運(yùn)行之前就已經(jīng)建立了。創(chuàng)建對(duì)象的惟一途徑是調(diào)用構(gòu)造函數(shù)。構(gòu)造函數(shù)時(shí)一段程序,所以構(gòu)造對(duì)象的先后順序不同,直接影響程序執(zhí)行的先后順序,導(dǎo)致不同的運(yùn)行結(jié)果。C++給構(gòu)造對(duì)象的順序做了專門的規(guī)定。
局部對(duì)象局部和靜態(tài)對(duì)象是指塊作用域(局部作用域)和文件作用域的對(duì)象。它們的聲明順序與它們?cè)诔绦蛑谐霈F(xiàn)的順序是一致的。見課本307頁例9.8在C中,所有的局部變量(沒有對(duì)象)都是在函數(shù)開始執(zhí)行時(shí)統(tǒng)一創(chuàng)建的,創(chuàng)建的順序是根據(jù)變量在程序中按語句行出現(xiàn)的順序。而C++卻不同,它是根據(jù)運(yùn)行中定義對(duì)象的順序來決定對(duì)象創(chuàng)建的順序。而且,靜態(tài)對(duì)象只創(chuàng)建一次。10/1/202329
全局對(duì)象和全局變量一樣,所有全局對(duì)象在主函數(shù)啟動(dòng)之前,全部已近被構(gòu)造。因?yàn)闃?gòu)造過程是程序語句的執(zhí)行過程,所以,可以想象在程序啟動(dòng)之前,已經(jīng)有程序語句(構(gòu)造函數(shù))在那里被執(zhí)行過了。同一工程不同代碼文件全局對(duì)象的創(chuàng)建沒有明確順序規(guī)定.對(duì)策:不要讓不同文件的全局對(duì)象互為依賴.因?yàn)橐蕾嚲哂邢群笮?,而其全局?duì)象的創(chuàng)建不能保證該依賴性發(fā)揮作用.全局對(duì)象在main函數(shù)啟動(dòng)之前生成,而調(diào)試則在main函數(shù)啟動(dòng)之后.對(duì)策:調(diào)試時(shí),應(yīng)先將全局對(duì)象作為局部對(duì)象來運(yùn)行觀察.或者,在構(gòu)造函數(shù)中添加輸出語句來觀察運(yùn)行過程.10/1/202330
成員對(duì)象成員對(duì)象的構(gòu)造順序按類定義的出現(xiàn)順序classA{public:A(int
x){
cout<<"A:"<<x<<"->";
}};//classB{public:B(int
x){
cout<<"B:"<<x<<"->";
}};//class C按A、B的順序定義對(duì)象成員,其構(gòu)造函數(shù)又按b、a的順序進(jìn)行構(gòu)造。到底聽誰的,以定義順序說了算。classC{A
a;B
b;public:C(int
x,int
y):b(x),a(y){
cout<<"C\n";
}};//-----------------------------------intmain(){C
c(15,9);}1/0/=/1=/2=02=3========================31
構(gòu)造位置全局?jǐn)?shù)據(jù)區(qū):全局對(duì)象,靜態(tài)全局對(duì)象,靜態(tài)局部對(duì)象,常對(duì)象類的靜態(tài)數(shù)據(jù)成員也存放在該數(shù)據(jù)區(qū)。目的是為了讓對(duì)象的生命周期與運(yùn)行的程序等壽命。棧區(qū):局部對(duì)象在函數(shù)中定義好、局部對(duì)象,隨著被調(diào)用的返回而析構(gòu)(銷毀)。動(dòng)態(tài)存儲(chǔ)區(qū)(也稱堆區(qū)):用new申請(qǐng)的對(duì)象用delete銷毀。特殊地址空間除此之外,還可以指定特殊地址空間,存放對(duì)象10/1/202332回顧10/1/2023335.拷貝構(gòu)造函數(shù)10/1/202334對(duì)象本體與對(duì)象實(shí)體:對(duì)象本體也是對(duì)象主體,對(duì)象實(shí)體則還包括屬于對(duì)象的衍生物,如,某個(gè)人體是人類對(duì)象的主體,然而某人還擁有父母,房產(chǎn)等屬于某人的世系或資產(chǎn),描述人的屬性不僅僅只是人體數(shù)據(jù).從形式上看,對(duì)象除了包括數(shù)據(jù)成員,還包括指向數(shù)據(jù)的指針.對(duì)象本體與對(duì)象實(shí)體是不一致就是說有時(shí)我們會(huì)需要把a(bǔ)對(duì)象的屬性全部轉(zhuǎn)給b對(duì)象,對(duì)象本體與對(duì)象實(shí)體一致就是你要將a對(duì)象的屬性賦給a對(duì)象本身。對(duì)于一個(gè)簡單的變量的初始化方法是用一個(gè)常量或變量初始化另一個(gè)變量,例如:double
x=12.36;double
y=x;疑問:前面介紹了用構(gòu)造函數(shù)初始化對(duì)象,那么能不能像簡單變量的初始化一樣,直接用一個(gè)對(duì)象來初始化另一個(gè)對(duì)象呢?答案是肯定的。例:以定義的一個(gè)Point類為例,說明用一個(gè)對(duì)象來初始化另一個(gè)對(duì)象。Point
pt1(10,20);Point
pt2=pt1;那么,后一句也可寫成Point
pt2(pt1);它是用pt1初始化pt2,此時(shí),pt2各個(gè)成員的值與pt1各個(gè)成員的值相同,也就是說,pt1各個(gè)成員的值被復(fù)制到pt2相應(yīng)的成員當(dāng)中。在這個(gè)初始化過,實(shí)際上調(diào)用了一個(gè)拷貝構(gòu)造函數(shù)。1程0/1/當(dāng)202中335拷貝構(gòu)造函數(shù):拷貝構(gòu)造函數(shù)是C++中引入的一種新的構(gòu)造函數(shù)。定義一個(gè)拷貝構(gòu)造函數(shù)的方式是:類名(const
類名
&形式參數(shù)){
函數(shù)體}由此可看出拷貝構(gòu)造函數(shù)的特點(diǎn):拷貝構(gòu)造函數(shù)的名稱與類的名稱相同,且它只有一個(gè)參數(shù),該參數(shù)就是對(duì)該類對(duì)象的引用。拷貝構(gòu)造函數(shù)的功能是用于實(shí)現(xiàn)對(duì)象值的拷貝,通過將一個(gè)同類對(duì)象的值拷貝給一個(gè)新對(duì)象,來完成對(duì)新對(duì)象的初始化,即用一個(gè)對(duì)象去構(gòu)造另外一個(gè)對(duì)象。(3)每個(gè)類都有一個(gè)拷貝構(gòu)造函數(shù)10/1/202336以本類對(duì)象為常量引用參數(shù)的構(gòu)造函數(shù):class
Date{public:Date();Date(const
Date&
d);//
...};Date
x; //調(diào)用無參構(gòu)造函數(shù)
Date
y(x);//調(diào)用拷貝構(gòu)造函數(shù)10/1/202337例:默認(rèn)拷貝構(gòu)造函數(shù):若類中沒有定義拷貝構(gòu)造函數(shù),則系統(tǒng)會(huì)悄悄定義一個(gè)默認(rèn)空拷貝構(gòu)造函數(shù):Date(const
Date&d){}默認(rèn)拷貝構(gòu)造函數(shù)體一定是空的.空拷貝構(gòu)造函數(shù)負(fù)責(zé)將傳遞的對(duì)象到新創(chuàng)的對(duì)象做對(duì)象本體的位對(duì)位拷貝.(甚至連指針值都相等,即與參數(shù)對(duì)象擁有共同的資源)10/1/202338自定義拷貝構(gòu)造函數(shù):為了達(dá)到對(duì)象實(shí)體也就是對(duì)象整體復(fù)制目的,就需要另外定義一個(gè)拷貝構(gòu)造函數(shù),以覆蓋默認(rèn)的拷貝構(gòu)造函數(shù):見課本例315頁9.13自定義拷貝構(gòu)造名也是類名,它是構(gòu)造函數(shù)的重載,一旦自定義了拷貝構(gòu)造函數(shù),默認(rèn)的拷貝構(gòu)造函數(shù)就不再起作用了。在自定義拷貝構(gòu)造函數(shù)之前,我們進(jìn)行拷貝對(duì)象構(gòu)造時(shí),都是在用默認(rèn)的拷貝構(gòu)造函數(shù),因?yàn)槟菚r(shí)的對(duì)象本體與對(duì)象實(shí)體是一致的。所以,自定義拷貝構(gòu)造函數(shù)在對(duì)象本體與對(duì)象實(shí)體不一致時(shí),便是需要的,否則無此需要。10/1/202339自定義拷貝構(gòu)造函數(shù)體的工作不負(fù)責(zé)位對(duì)位對(duì)象復(fù)制,一般來說,它負(fù)責(zé)資源分配和由此而來的指針修改.
class
Person{char*
pName;public:Person(char*
pN="noName"){pName
=newchar[strlen(pN)+1];if(pName)
strcpy(pName,pN);}Person(const
Person&
s){pName
=newchar[strlen(s.pName)+1];if(pName)
strcpy(pName,
s.pName);}~Person(){delete[]
pName;}10/1/20}2;3406.析構(gòu)函數(shù)10/1/202341當(dāng)一個(gè)對(duì)象被定義時(shí),系統(tǒng)自動(dòng)調(diào)用構(gòu)造函數(shù)為該對(duì)象分配相應(yīng)的資源,當(dāng)對(duì)象使用完畢后,這些系統(tǒng)資源需要在對(duì)象消失前被釋放。人為的動(dòng)態(tài)內(nèi)存釋放工作由析構(gòu)函數(shù)來完成,析構(gòu)函數(shù)時(shí)一種特殊的成員函數(shù),它的意義是做關(guān)于對(duì)象失效之前瞬間的
善后工作。它的功能與構(gòu)造函數(shù)的工作正好相反,是用來釋放
一個(gè)對(duì)象。我們知道有內(nèi)存申請(qǐng),也就有內(nèi)存釋放。一般來說,需要定義構(gòu)造函數(shù)的類也需要定義析構(gòu)函數(shù),不需要構(gòu)造函數(shù)
的類,也無須定義析構(gòu)函數(shù)。所以析構(gòu)函數(shù)和構(gòu)造函數(shù)是成對(duì)
出現(xiàn)的。定義:10/1/202342析構(gòu)函數(shù)的定義方式為:~類名(){函數(shù)體}特點(diǎn):析構(gòu)函數(shù)名與構(gòu)造函數(shù)名相同,但它前面必須加一個(gè)“~”,用以與析構(gòu)函數(shù)相區(qū)別;在定義析構(gòu)函數(shù)時(shí),不能指定任何返回類型,也沒有參數(shù),而且不能重載。因此在一個(gè)類中只能有一個(gè)析構(gòu)函數(shù)。析構(gòu)函數(shù)可以被用戶調(diào)用,也可以被系統(tǒng)調(diào)用。在下面兩種情況下,析構(gòu)函數(shù)會(huì)被自動(dòng)調(diào)用a、如果一個(gè)對(duì)象被定義在一個(gè)函數(shù)體內(nèi),則當(dāng)這個(gè)函數(shù)結(jié)束時(shí),該對(duì)象的析構(gòu)函數(shù)被自動(dòng)調(diào)用。b、當(dāng)一個(gè)對(duì)象是使用new運(yùn)算符動(dòng)態(tài)創(chuàng)建時(shí)的,在使用delete運(yùn)算符自動(dòng)釋放時(shí),delete將會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù)。每一個(gè)類若沒有顯示地定義為一個(gè)類定義析構(gòu)函數(shù),編譯系統(tǒng)會(huì)自動(dòng)地生成一個(gè)默認(rèn)的析構(gòu)函數(shù),默認(rèn)析構(gòu)函數(shù)時(shí)一個(gè)空函數(shù),實(shí)際上什么操作都不進(jìn)行。10/1/202343例:程序中三個(gè)類A、B、C分別有一個(gè)析構(gòu)函數(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";
}};//-------------------------void
func(){cout<<"\nfunc:
";A
a;cout<<"ok->";static
B
b;C
c;}//----------------------------intmain(){cout<<"main:
";for(int
i=1;
i<=2;
++i){for(int
j=1;
j<=2;
++j)if(i==2)
C
c;
else
A
a;B
b;}func();func();}//=================10/1/202344注:(1)析構(gòu)函數(shù)總是出現(xiàn)在對(duì)象的生命期結(jié)束之時(shí)。靜態(tài)對(duì)象在程序運(yùn)行結(jié)束時(shí)析構(gòu)。對(duì)于一個(gè)簡單的類來說,大多可以直接使用系統(tǒng)提供的默認(rèn)析構(gòu)函數(shù)。但是,如果在類的對(duì)象中分配有動(dòng)態(tài)內(nèi)存(如:用new申請(qǐng)分配的內(nèi)容)時(shí),就必須為該類提供適當(dāng)?shù)奈鰳?gòu)函數(shù),完成清理工作。對(duì)象被析構(gòu)的順序與對(duì)象建立時(shí)的順序正好相反。對(duì)象析構(gòu)與構(gòu)造函數(shù)的關(guān)系是棧數(shù)據(jù)結(jié)構(gòu)中的入棧和出棧的關(guān)系,即最后構(gòu)造的對(duì)象先被析構(gòu)。棧底封閉指針10/1/2023457.
對(duì)象轉(zhuǎn)型與賦值
用于轉(zhuǎn)型的構(gòu)造函數(shù)5/8與5.0/8的結(jié)果是不同的,原因是C++執(zhí)行了兩種不同的操作。編譯器會(huì)將5.0/8中的整數(shù)8自動(dòng)轉(zhuǎn)換成double,匹配兩個(gè)
double數(shù)的除法操作。這是內(nèi)部數(shù)據(jù)類型所具有的轉(zhuǎn)換功能。但是,對(duì)于類類型,其自動(dòng)轉(zhuǎn)換的功能必須編程實(shí)現(xiàn)。那就是定義一個(gè)含有一個(gè)參數(shù)的構(gòu)造函數(shù)。例:class
Student{public:Student(const
string&n);};void
fn(Student&
s);intmain(){string
t=“jenny”;fn(t);//參數(shù)為string,卻能匹配Student類型1}0/1/202346剛才的例子也是在告知,如何將string對(duì)象轉(zhuǎn)換成一個(gè)Student對(duì)象。如果有重載函數(shù):void fn(string
&s){cout<<“ok\n”;}則main函數(shù)中的fn(t)函數(shù)調(diào)用將會(huì)馬上匹配。否則,匹配了void
fn(Student&
s)函數(shù)。從fn(Student&)和Student(conststring)可以推得fn(string)調(diào)用,這就是構(gòu)造函數(shù)用來從一種類型轉(zhuǎn)換成另一種類型的能力。對(duì)象轉(zhuǎn)型的規(guī)則:只會(huì)嘗試含有一個(gè)參數(shù)的構(gòu)造函數(shù)如果有二義性,則會(huì)放棄嘗試推導(dǎo)是一次性的,不允許多步推導(dǎo)10/1/202347
對(duì)象拷貝對(duì)象賦值即對(duì)象拷貝:兩個(gè)已經(jīng)存在的對(duì)象之間的復(fù)制Person
d(“Ranny”)Person
g;d=g; //對(duì)象賦值對(duì)象賦值便是使用類中的賦值操作符.如果類中沒有定義賦值操作符,則系統(tǒng)悄悄地定義一個(gè)默認(rèn)的賦值操作符:Person&
operator=(const
Person&
p){memcpy(*this,
*p,
sizeof(p));}10/1/202348當(dāng)對(duì)象本體與對(duì)象實(shí)體不同時(shí),則對(duì)象賦值操作符與拷貝構(gòu)造函數(shù)一樣
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國電子消毒柜內(nèi)配線數(shù)據(jù)監(jiān)測(cè)研究報(bào)告
- COPD患者壓力知覺、心理一致感與睡眠質(zhì)量的現(xiàn)狀及相關(guān)性研究
- 2025年安徽礦業(yè)職業(yè)技術(shù)學(xué)院高職單招職業(yè)技能測(cè)試近5年常考版參考題庫含答案解析
- 2025年安徽中澳科技職業(yè)學(xué)院高職單招高職單招英語2016-2024歷年頻考點(diǎn)試題含答案解析
- 砼水池施工方案
- 施工方案選擇包括
- 2025年天津廣播影視職業(yè)學(xué)院高職單招職業(yè)適應(yīng)性測(cè)試近5年常考版參考題庫含答案解析
- 2025年大連翻譯職業(yè)學(xué)院高職單招高職單招英語2016-2024歷年頻考點(diǎn)試題含答案解析
- 2025年四川電子機(jī)械職業(yè)技術(shù)學(xué)院高職單招語文2018-2024歷年參考題庫頻考點(diǎn)含答案解析
- 四年級(jí)數(shù)學(xué)(小數(shù)加減運(yùn)算)計(jì)算題專項(xiàng)練習(xí)與答案
- 光伏自發(fā)自用項(xiàng)目年用電清單和消納計(jì)算表
- 量子計(jì)算在醫(yī)學(xué)圖像處理中的潛力
- 阿里商旅整體差旅解決方案
- 浙江天臺(tái)歷史文化名城保護(hù)規(guī)劃說明書
- 邏輯思維訓(xùn)練500題
- 第八講 發(fā)展全過程人民民主PPT習(xí)概論2023優(yōu)化版教學(xué)課件
- 實(shí)體瘤療效評(píng)價(jià)標(biāo)準(zhǔn)RECIST-1.1版中文
- 企業(yè)新春茶話會(huì)PPT模板
- GB/T 19185-2008交流線路帶電作業(yè)安全距離計(jì)算方法
- DIC診治新進(jìn)展課件
- 公路工程施工現(xiàn)場(chǎng)安全檢查手冊(cè)
評(píng)論
0/150
提交評(píng)論