版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第3章關(guān)于類和對象的進(jìn)一步討論
3.1構(gòu)造函數(shù)
3.2析構(gòu)函數(shù)
3.3調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序
3.4對象數(shù)組
3.5對象指針
3.6共用數(shù)據(jù)的保護(hù)
3.7對象的動態(tài)建立和釋放
3.8對象的賦值和復(fù)制
3.9靜態(tài)成員
3.10友元
3.H類模板
1/145
3.1構(gòu)造函數(shù)(constructor:ctor)
如果定義一個變量,而程序未對其進(jìn)行初始化的話,這個
變量的值是不確定的,因為c和C++不會自覺地去為它賦
值。與此相似,如果定義一個對象,而程序未對其數(shù)據(jù)成
員進(jìn)行初始化的話,這個對象的值也是不確定的。
3.1.1對象的初始化
3.1.2構(gòu)造函數(shù)的作用
3.1.3帶參數(shù)的構(gòu)造函數(shù)
3.1.4用參數(shù)初始化表初始化數(shù)據(jù)成員
3.1.5構(gòu)造函數(shù)的重載
3.1.6使用默認(rèn)參數(shù)的構(gòu)造函數(shù)左0
#S
8Er小
2/145r?
:
311對象的初始化
?因為類是一種類型,是創(chuàng)建對象的藍(lán)圖,系統(tǒng)不會為它分
配內(nèi)存空間。
?所以在定義類時,不能給數(shù)據(jù)成員賦初值,要在建立對象
時,給數(shù)據(jù)成員賦初值。否則對象的狀態(tài)是不確定的。
如果類單輸音纏成員是公有的,可以在定義對象時對
其數(shù)據(jù)嫡初始化。
例如:inthour;
intminute;在一個大括號內(nèi)順序列出各個公有
數(shù)據(jù)成員的值,在兩個值之間用逗
intsec;號分隔。注意這只能用于數(shù)據(jù)成員
都是公有的情況。
);
Timetl{15,36,26);
3/145
z\在前面的例子里,是用成員函數(shù)對對象的數(shù)據(jù)成員賦初值,
V如果一個類定義了多個對象,對每個對象都要調(diào)用成員函
數(shù)對數(shù)據(jù)成員賦初值,那么程序就會變得煩瑣,所以用成
員函數(shù)為數(shù)據(jù)成員賦初值絕不是一人好方法。按理說對象
的創(chuàng)建跟上帝造萬物一樣,萬物誕生的時候都是有各自的
特征的。對象的初始屬性應(yīng)該是與生俱來的才是最自然的。
4/145
312構(gòu)造函數(shù)的作用
C++提供了構(gòu)造函數(shù)機(jī)制,用來為對象的數(shù)據(jù)成員進(jìn)
行初始化。在前面一直未提及這個概念,其實如果你未
設(shè)計構(gòu)造函數(shù),系統(tǒng)在創(chuàng)建對象時,會自動提供一個默
認(rèn)的構(gòu)造函數(shù),什么也不做。
構(gòu)造函數(shù)用于為對象初始化,它屬于某一個類,可以由系
統(tǒng)自動生成。也可以由程序員編寫,程序員根據(jù)初始化的
要求設(shè)計構(gòu)造函數(shù)及函數(shù)參數(shù)。
構(gòu)造函數(shù)是一種特殊的成員函數(shù),在程序中不需要寫調(diào)用
語句,在系統(tǒng)建立對象時由系統(tǒng)自覺調(diào)用執(zhí)行。
5/145
構(gòu)造函數(shù)的特點:
(1)構(gòu)造函數(shù)的名字與它的類名必須相同。
(2)它沒有類型,也不返回值
(3)它可以帶參數(shù),也可以不帶參數(shù)。
6/145
例3.1在例2.3的基礎(chǔ)上定義構(gòu)造成員函數(shù)
ttinclude<iostream>voidTime::set_time()
usingnamespacestd;
{cin>>hour;
classTime
cin>>minute;
(public:
Time()cin>>sec;
{hour=0;)
minute=0;
sec=0;
voidTime::show_time()
}
{
voidset_time();
voidshow_time();cout<<hour<<zz:〃:〃
private:<<sec<<endl;
inthour;
intminute;
intsec;
);
7/145
intmain()
在類Time中定義了構(gòu)造函數(shù)
Time,它與所在的類同名。
Timetl;在建立對象時自動執(zhí)行構(gòu)造
tl.set_time();函數(shù),該函數(shù)的作用是為對
象中的各個數(shù)據(jù)成員賦初值
tl.show_time();
0o注意只有執(zhí)行構(gòu)造函數(shù)
Timet2;時才為數(shù)據(jù)成員賦初值。
t2.show_time();
return0;
8/145
程序運行的情況為:
102554
10:25:54〃輸出tl的值
0:0:0//輸出t2的值
也可以在類內(nèi)聲明構(gòu)造函數(shù)然后在類外定義構(gòu)造函數(shù)。將
程序修改為:
Time();〃類內(nèi)聲明
然后在類外定義構(gòu)造函數(shù):
Time::Time()〃類外定義
{hour=0;
minute=0;
sec=0;
}9/145
1)關(guān)于構(gòu)造函數(shù)的使用
7
(1)什么時候調(diào)用構(gòu)造函數(shù)呢?當(dāng)函數(shù)執(zhí)行到對象401
句時建立對象,此時就要調(diào)用構(gòu)造函數(shù),對象就有了自己
的作用域,對象的生命周期開始了。
(2)構(gòu)造函數(shù)沒有返回值,因此不需要在定義中聲明類型。
(3)構(gòu)造函數(shù)不需要顯式地調(diào)用,構(gòu)造函數(shù)是在建立對象
日寸由系統(tǒng)自動執(zhí)行的,且只執(zhí)行一次。構(gòu)造函數(shù)一般定義
為public。
(4)在構(gòu)造函數(shù)中除了可以對數(shù)據(jù)成員賦初值,還可以使
用其他語句。
(5)如果用戶沒有定義構(gòu)造函數(shù),C++系統(tǒng)會自動生成一
個構(gòu)造函數(shù),而這個函數(shù)體是空的,不執(zhí)行初始化操作。
10/145
313帶形參數(shù)的構(gòu)造函數(shù)
可以采用帶參數(shù)的構(gòu)造函數(shù),使得對象取得初始確定值。
構(gòu)造函數(shù)格式:
構(gòu)造函數(shù)名(類型形參1,類型形參2,…)
Time(inth,intm,ints)
{hour=h;
minute二m;
sec二s;
}
在定義對象時指定實參,定義對象的格式為:
類名對象名(實參1,實參2,…);
Timetl(12,30,3禽45
例3.2有兩個長方柱,其長、寬、高分別為:
(1)12z25z30
(2)15z30z21
編寫程序,在類中用帶參數(shù)的構(gòu)造函數(shù),計算它們的體積。
分析:可以在類中定義一個計算長方體體積的成員函數(shù)計
算對象的體積。
H
12/145
ttinclude<iostream>〃長方體構(gòu)造函數(shù)
usingnamespacestd;Box::Box(inth,intw,intlen)
classBox{height=h;
{public:width=w;
Box(int,int,int);length=len;
intvolume();
//計算長方體的體積
private:
intBox::volume()
intheight;
intwidth;return(height^width*length);
intlength;
);
13/145
intmain()
Boxboxl(12,25,30);//定義對象boxl
cout〈〈〃boxl體積=〃〈〈boxl.volume()<<endl;
Boxbox2(15,30,21);//定義對象box2
cout<<〃box2體積=〃〈〈box2.volume()<<endl;
return0;
}____________________________________________
O提醒:
(1)帶形參的構(gòu)造函數(shù)在定義對象時必須指定實參
(2)用這種方法可以實現(xiàn)不同對象的不同的初始化。
14/145
Note
314用參數(shù)初始化表對數(shù)據(jù)成員初始化
C++提供了參數(shù)初始化表的方法對數(shù)據(jù)成員初始化。這種方法不必在構(gòu)
造函數(shù)內(nèi)對數(shù)據(jù)成員初始化,在函數(shù)的首部就能實現(xiàn)數(shù)據(jù)成員初始化。
函數(shù)名(類型1形參1,類型2形參2):成員名1(形參1),成員名2(形參2)
{}〃函數(shù)體可以為空。
Time(inth,intm,ints):hour(h),minute(m),sec(s)
功能:執(zhí)行構(gòu)造函數(shù)時,將形參1的值賦予成員1,將形參2的值賦予成
員2,形參的值由定義對象時的提供的實參值決定。
此時定義對象的格式依然是帶實參的形式:
類名對象名(實參1,實參2);
Timetl(8,7,6);
15/145
:
例:定義帶形參初始化表的構(gòu)造函數(shù)
Box::Box(inth,intw,intlen):height(h),
width(w),length(len){}||
冒號作為分隔符
定義對象:
Boxboxl(12,25,30);|
...逗號分隔的初始化列表
Boxbox2(15,30,21);
16/145
315構(gòu)造函數(shù)的重載
構(gòu)造函數(shù)也可以重載。一個類可以有多個同名構(gòu)造函數(shù),
函數(shù)參數(shù)的個數(shù)、參數(shù)的類型各不相同。
例3.3:在例3.2的基礎(chǔ)上定義兩個構(gòu)造函數(shù)其中一個無參
數(shù),另一個有參數(shù)。
17/145
ttinclude<iostream>
usingnamespacestd;
classBox
{public:
Box();x.
Box(inth,,intlen)height(h),
width(w),length(leSl{}
intvolume();
private:\
intheight;\Box::Box()
intwidth;\{height=10;
}intBox::volume()
intlength;\wliedntght=h1=01;0;
{return(height*width*length);
);
I18)145
intmain()
Boxboxl;
cout<<z/boxl體積二〃<<boxl.volume()<<endl;
Boxbox2(15,30,25);
cout<<zzbox2體積二〃<<box2.volume()<<endl;
return0;
例子中定義了兩個構(gòu)造函數(shù),一個無參數(shù)另一個帶三個參
數(shù)。系統(tǒng)根據(jù)對象定義的形式?jīng)Q定調(diào)用哪個構(gòu)造函數(shù)。
對象boxl沒有實參,系統(tǒng)調(diào)用無參數(shù)的構(gòu)造函數(shù);對象box2
帶三個實參,系統(tǒng)調(diào)用帶形參的構(gòu)造函數(shù)。
說明:
_(1)不帶形參的構(gòu)造函數(shù)為默認(rèn)構(gòu)造函數(shù),每個類只有一
一個默認(rèn)構(gòu)造函數(shù),如果只定義無參對象,則系統(tǒng)自動提供
空白構(gòu)造函數(shù)。如果既有無參對象也有帶參對象,必須人
為定義一個無參構(gòu)造函數(shù)。
(2)雖然每個類可以包含多個構(gòu)造函數(shù),但是創(chuàng)建對象時,
系統(tǒng)僅執(zhí)行其中一個。
20/145
316使用默認(rèn)參數(shù)值的構(gòu)造函數(shù)
?C++允許在構(gòu)造函數(shù)里為形參指定默認(rèn)值,如果創(chuàng)建對象時,
未給出相應(yīng)的實參時,系統(tǒng)將用形參的默認(rèn)值為形參賦值。
格式:
函數(shù)名(類型形參上常數(shù),類型形參2二常數(shù),…);
例3.4:將例3.3中的構(gòu)造函數(shù)改用帶默認(rèn)值的參數(shù),長、寬、
高的默認(rèn)值都是10。
21/145
ttinclude<iostream>
usingnamespacestd;
classBox
(public:
Box(intw=10,inth=10,intlen=10);
intvolume();
private:
intheight;
intwidth;
intlength;
);
22/145
Box::Box(intw,inth,intlen)
{height=h;
width=w;
length=len;
}
intBox::volume()
{return(height*width*length)
23/145
intmain()
(
Boxboxl;
cout<<z/boxl體積=z,<<boxl.volume()<<endl;
Boxbox2(15);
cout<<z/box2體積zz<<box2.volume()<<endl;
Boxbox3(15,30);
cout<<z/box3體積zz<<box3.volume()<<endl;
Boxbox4(15,30,20);
cout<<z/box4體積〃〈〈box4.volume()<<endl;
return0;
24/145
程序運行結(jié)果為:
boxl體積=1000
box2體積=1500
box3體積=4500
box4體積二9000
構(gòu)造函數(shù)也可以改寫成帶參數(shù)初始化表的形式:
Box::Box(inth,intw,intlen):height(h),
width(w),length(len){}
整個函數(shù)只需一行,簡單方便。
25/145
在構(gòu)造函數(shù)中使用默認(rèn)參數(shù)提供了建立對象的多種選擇,
它的作用相當(dāng)于多個重載構(gòu)造函數(shù)。
說明:
(1)如果在類外定義構(gòu)造函數(shù),應(yīng)該在聲明構(gòu)造函數(shù)時指
足默認(rèn)參數(shù)值,在定義函數(shù)時可以不再指定默認(rèn)參數(shù)值。
在相反情況下,如果定義了無參對象,則編譯器報錯:沒
有合適的構(gòu)造函數(shù)。
(2)在聲明構(gòu)造函數(shù)時,形參名可以省略例如:
Box(int=10,int=10,int=10);
等號不可省略。、
26/145
(3)如果構(gòu)造函數(shù)的所有形參都指定了默認(rèn)值,在定義對
象時,可以指定實參也可不指定實參。由于不指定實參也
可以調(diào)用構(gòu)造函數(shù),因此全部形參都指定了默認(rèn)值的構(gòu)造
函數(shù)也屬于默認(rèn)構(gòu)造函數(shù)。為了避免歧義,不允許同時定
義不帶形參的構(gòu)造函數(shù)和全部形參都指定默認(rèn)值的構(gòu)造函
數(shù)。
(4)同樣為了避免歧義性,如定義了全部形參帶默認(rèn)值的
構(gòu)造函數(shù)后,不能再定義重載構(gòu)造函數(shù)。反之亦然。
27/145
Box(int=10,int=10,int=10);
Box();
Box(int,int);
若定義對象:
Boxboxl;
Boxbox2(15,30);
這時應(yīng)該調(diào)用哪個構(gòu)造函數(shù)呢?J
如果構(gòu)造函數(shù)中參數(shù)并非都帶默認(rèn)值時,要具體分析情況。
如有以下三個原型聲明:
28/145
Box();
Box(int,int=10,int=10);
Box(int,int);
若定義對象:
Boxboxl;〃正確,調(diào)用第一個
Boxbox2(15);//調(diào)用第二個
Boxbox3(15,30);//不知調(diào)用哪一個
因此不要同時使用重載構(gòu)造函數(shù)和帶默認(rèn)值的構(gòu)造函數(shù)。
■
n
29/145W
3.1構(gòu)造函數(shù)
3.2析構(gòu)函數(shù)
3.3調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序
3.4對象數(shù)組
3.5對象指針
3.6共用數(shù)據(jù)的保護(hù)
3.7對象的動態(tài)建立和釋放
3.8對象的賦值和復(fù)制
3.9靜態(tài)成員
3.10友元U
3.11類模板.
30/145S
3.2析構(gòu)函數(shù)(destructor:dtor)
析構(gòu)函數(shù)也是個特殊的成員函數(shù),它的作用與構(gòu)造函數(shù)相
反,當(dāng)對象的生命周期結(jié)束時,系統(tǒng)自動調(diào)用析構(gòu)函數(shù),
收回對象占用的內(nèi)存空間。
執(zhí)行析構(gòu)函數(shù)的時機(jī):
①在一個函數(shù)內(nèi)定義的對象,當(dāng)這個函數(shù)結(jié)束時,自動執(zhí)行
析構(gòu)函數(shù)釋放對象。
②static局部對象要到main函數(shù)結(jié)束或執(zhí)行exit命令時才
自動執(zhí)行析構(gòu)函數(shù)釋放對象。
③全局對象(在函數(shù)外定義的對象)當(dāng)main函數(shù)結(jié)束或執(zhí)
行exit命令時自動執(zhí)行析構(gòu)函數(shù)釋放對象。
④如果用new建立動態(tài)對象,用delete時自動執(zhí)行析構(gòu)函數(shù)
釋放對象。
31/145
析構(gòu)函數(shù)的特征
①析構(gòu)函數(shù)名以符號開始后跟類名
②析構(gòu)函數(shù)沒有數(shù)據(jù)類型、返回值、形參。由于沒有形參
所以析構(gòu)函數(shù)不能重載。一個類只有一個析構(gòu)函數(shù)。
③如果程序員沒有定義析構(gòu)函數(shù),C++編譯系統(tǒng)會自動生成
一個析構(gòu)函數(shù)。
析構(gòu)函數(shù)除了釋放對象(資源)外,還可以執(zhí)行程序員在
最后一次使用對象后希望執(zhí)行的任何操作。例如輸出有關(guān)
的信息。
32/145
例3.5包含構(gòu)造函數(shù)和析構(gòu)函數(shù)的C++程序
ttinclude<iostream>
ttinclude<string>
usingnamespacestd;
classStudent
{public:
Student(intn,stringnam,chars)
{num=n;
name=nam;
sex二s;
cout<<z/Construetorcalled.z/<<endl;
33/145
Student()
{cout<<z,Destruetorcalled.z/<<endl;}
voiddisplay()
{cout<<z/num:z/<<num<<endl;
cout<<z/name:zz<<name<<endl;
cout<<z/sex:z/<<sex<<endl<<endl;
}
private:
intnum;
stringname;
charsex;
);
34/145
intmain()
{Studentstudl(10010,z,Wang_liz,,,f?);
studl.display();
Studentstud2(10011,〃Zhang_fun〃,';
stud2.display();
return0;
n
35/145
main函數(shù)前聲明的類其作用域是全局的。
程序運行結(jié)果如下:
Constructorcalled.
num:10010
name:Wang_li
sex:f
Constructorcalled.
num:10011
name:Zhangfun
sex:m
Destructorcalled.
Destructorcalled.
36/145
3.1構(gòu)造函數(shù)
3.2析構(gòu)函數(shù)
3.3調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序
3.4對象數(shù)組
3.5對象指針
3.6共用數(shù)據(jù)的保護(hù)
3.7對象的動態(tài)建立和釋放
3.8對象的賦值和復(fù)制
3.9靜態(tài)成員
3.10友元■
類模板Cm
3.HC
Mi
37/145.蠢
3.3調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序
?在使用構(gòu)造函數(shù)和析構(gòu)函數(shù)時需要特別注意對它們的調(diào)用
時間和調(diào)用順序。
?在一般情況下,調(diào)用析構(gòu)函數(shù)的次序與調(diào)用構(gòu)造函數(shù)的次
序恰好相反:最先調(diào)用構(gòu)造函數(shù)的對象,最后調(diào)用析構(gòu)函
數(shù)。而最后調(diào)用構(gòu)造函數(shù)的對象,最先調(diào)用析構(gòu)函數(shù)。可
簡記為:先構(gòu)造的后析構(gòu),后構(gòu)造的先析構(gòu),它相當(dāng)于一
個棧,后進(jìn)先出。
38/145
對象1的對象1的
構(gòu)造函數(shù)析構(gòu)函數(shù)
對象2的對象2的
構(gòu)造函數(shù)析構(gòu)函數(shù)
對象3的[對象3的
構(gòu)造函數(shù)"I析構(gòu)函數(shù)
39/145
構(gòu)造析構(gòu)順序總結(jié):
在一般情況下,調(diào)用析構(gòu)函數(shù)的次序與調(diào)用構(gòu)造函數(shù)
的次序相反,這是對同一類存儲類別的對象而言的。
⑴在全局范圍中定義的對象(在所有函數(shù)之外定義的對
象),在主函數(shù)執(zhí)行前調(diào)用構(gòu)造函數(shù)。當(dāng)主函數(shù)結(jié)束時,
調(diào)用析構(gòu)函數(shù)。
⑵在函數(shù)中定義靜態(tài)局部對象,則在第一次調(diào)用該函
數(shù)建立對象時調(diào)用構(gòu)造函數(shù),在主函數(shù)結(jié)束或調(diào)用
exit函數(shù)時才調(diào)用析構(gòu)函數(shù)。
⑶局部自動對象,在創(chuàng)建對象時調(diào)用構(gòu)造函數(shù)。如多次調(diào)
用對象所在的函數(shù),則每次創(chuàng)建對象時都調(diào)用構(gòu)造函數(shù)。
在函數(shù)調(diào)用結(jié)束時調(diào)用析構(gòu)函數(shù)。
40/145
例如:
Voidfn()
{studentstl;〃定義局部自動對象
staticstudentst2;〃定義靜態(tài)局部對象
???
)
對象stl是每次調(diào)用函數(shù)fn時調(diào)用構(gòu)造函數(shù),在函數(shù)fn結(jié)
束時調(diào)用析構(gòu)函數(shù)。
對象st2是第一次調(diào)用函數(shù)fn時調(diào)用構(gòu)造函數(shù),在函數(shù)fn
結(jié)束時并不調(diào)用析構(gòu)函數(shù),在到主函數(shù)結(jié)束時才調(diào)用析構(gòu)
函數(shù)。
41/145
3.1構(gòu)造函數(shù)
3.2析構(gòu)函數(shù)
3.3調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序
3.4對象數(shù)組
3.5對象指針
3.6共用數(shù)據(jù)的保護(hù)
3.7對象的動態(tài)建立和釋放
3.8對象的賦值和復(fù)制
3.9靜態(tài)成員
3.10友元
3.H類模板
42/145
3.4對象數(shù)組(較少使用)
類是一種特殊的數(shù)據(jù)類型,它當(dāng)然是C++的合法類型,
自然就可以定義對象數(shù)組。在一個對象數(shù)組中各個元素
都是同類對象例如一個班級有50個學(xué)生,每個學(xué)生具有
學(xué)號、年齡、成績等屬性,可以為這個班級建立一個對
象數(shù)組,數(shù)組包括了50個元素:
studentstd[50];
給數(shù)組初始化時,不可以用如下形式:
Studentstu[3]={1,7,6};
43/145
錯誤提示:分別在DevC++和VC++6.0下
23};
24intmain()
{Studentstu[3]={l,7,6};
5.5八..,犍QfnrnldiQnln\fCy?
intmain()
〈Studentstu[3]=<1,7,6};
stu[0].displayO;
stu[1].displayO;
stu[2].displayO;
return0;
}
I
■ration:defaultparal-Win32Debug
|MyProjects\defaultpara1\dest?cpp(26)::errorC244G:'initializing':cannotconuertfrom'constint'to'classStudent
tudioVMyProiecl.conversionfrom'inftonon-scalartype'Student1requested
tudio\MyProject..conversionfrom'inftonon-scalartype'Student1requested
44/145
數(shù)組的正確初始化
如果構(gòu)造函數(shù)有多個參數(shù),在花括號中為每個對象分別寫
上構(gòu)造函數(shù)并指定實參。格式為:
studentst[n]={student(實參1,實參2,實參3);
??????
student(實參1',實參2',實參3');
);
45/145
初始化數(shù)組樣例
假定對象有三個數(shù)據(jù)成員:學(xué)號、年齡、成績。下面定義
有三個學(xué)生的對象數(shù)組:
studentstd[3]={student(1001,18,87),
student(1002,19,76),
student(1003,18,80)
);〃構(gòu)造函數(shù)帶實參
在建立對象數(shù)組時,分別調(diào)用構(gòu)造函數(shù),對每個對象初始
化。每個元素的實參用括號括起來,實參的位置與構(gòu)造函
數(shù)形參的位置一一對應(yīng)。
46/145
例3.6對象數(shù)組的使用方法。(長方體數(shù)組)
#include<iostream>
usingnamespacestd;
classBox
{public:
Box(inth=10zintw=12,intlen=15):height(h)/width(w)/length(len)
{}〃帶默認(rèn)參數(shù)值和參數(shù)表
intvolume();
private:
intheight;
intwidth;
intlength;
);
47/145
intBox::volume()
{return(height*width*length);}
intmain()
Boxa[3]={Box(10,12,15),〃每個數(shù)組元素是一個對象
Box(15,18,20),
Box(16,20,26)};
cout<<”a[0]的體積是"<<a[0].volume()<<endl;
cout<<”a[l]的體積是"<<a[l].volume()<<endl;
cout<<”a[2]的體積是"<<a[2].volume()<<endl;
return0;
)
48/145
3.1構(gòu)造函數(shù)
3.2析構(gòu)函數(shù)
3.3調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序
3.4對象數(shù)組
3.5對象指針
3.6共用數(shù)據(jù)的保護(hù)
3.7對象的動態(tài)建立和釋放
3.8對象的賦值和復(fù)制
3.9靜態(tài)成員
3.10友元
3.H類模板
49/145
3.5對象指針
指針的含義是內(nèi)存單元的地址,可以指向一般的變量,也
可以指向?qū)ο蟆?/p>
50/145
3.5.1指向?qū)ο蟮闹羔?/p>
3.5.2指向?qū)ο蟪蓡T的指針
3.5.3this指針
51/145
351指向?qū)ο蟮闹羔?/p>
■對象在內(nèi)存占據(jù)一片連續(xù)的內(nèi)存空間,CPU都按地址訪問內(nèi)
存,對象在內(nèi)存的起始地址稱為對象指針。
定義對象的指針變量以保存對象的地址,方便引用對象成員,
格式如下:
類名*變量名;
Student*pstu;
定義好指針變量后,必須先給賦予合法的地址后才能使用。
一般是通過取地址運算取得另外一對象的地址,然后賦給
指針變量。
八Studentstul;
'?\pstu=&stul;
要用與對象類型相同的指針變量保存運算的結(jié)果。
rfB㈤F
52/145
classTimevoidTime::set_time()
(public:{cin>>hour;
Time()cin>>minute;
{hour=0;cin>>sec;
minute=0;}
sec=0;voidTime::show_time()
){cout<<hour<</z:〃:〃〈〈sec〈
voidset_time();<endl;
voidshow_time();
private:
inthour;
intminute;
intsec;
);
53/145
在此基礎(chǔ)上,有以下語句:
intmain()
(Time*pt;//定義pt是指向Time類對象的指針
Timetl;//定義Time類對象tl
pt=&tl;//將對象tl的地址賦予pt
(*pt).show_time()〃用指針變量訪問對象的成員。
pt->show_time()
54/145
3.5.2指向?qū)ο蟪蓡T的指針
對象由成員組成。對象占據(jù)的內(nèi)存區(qū)是各個數(shù)據(jù)成員占據(jù)
的內(nèi)存區(qū)的總和。對象成員也有地址,即指針。
「指向數(shù)據(jù)成員的指針
指針
I指向成員函數(shù)的指針。
H
55/145
1.指向?qū)ο蠊袛?shù)據(jù)成員的指針
①定義數(shù)據(jù)成員的指針變量
數(shù)據(jù)類型*指針變量名
②取得公有數(shù)據(jù)成員的地址
&對象名.成員名
這里的數(shù)據(jù)類型是數(shù)據(jù)成員的數(shù)據(jù)類型。
例:
Timetl;
int*pl;//定義一個指向整型數(shù)據(jù)的指針變量
pl=&tl.hour;〃假定hour是公有成員
cout<<*pl<<endl;
,二
?實際上類的數(shù)據(jù)成員是不公開的。所以這個方法不常用。
56/145
2.指向?qū)ο蟪蓡T函數(shù)的指針
①定義指向成員函數(shù)的指針變量
數(shù)據(jù)類型(類名::*變量名)(形參表);
void(Student::*pf)();
數(shù)據(jù)類型:成員函數(shù)的類型。
類名:對象所屬的類
變量名:按標(biāo)識符規(guī)則取名
形參表:指定成員函數(shù)的形參表(形參個數(shù)、類型)
②取成員函數(shù)的地址
&類名::成員函數(shù)名
&Student::display
在VC++系統(tǒng)中,也可以不寫&。為了與C語言一致,建議不要省略
57/145
③給指針變量賦初值
指針變量名二&類名::成員函數(shù)名;
④用指針變量調(diào)用成員函數(shù)
(對象名.*指針變量名)([實參表]);
對象名:是指定調(diào)用成員函數(shù)的對象。
*:明確其后的是一個指針變量。
實參表:與成員函數(shù)的形參表對應(yīng),如無形參,可以省略
實參表。
■
3
58/145
例3.7有關(guān)對象指針的使用方法
ttinclude<iostream>Time::Time(inth,intm,ints)
usingnamespacestd;{hour=h;
classTimeminute=m;
{public:sec=s;
Time(int,int,int)
voidTime::get_time()
inthour;
intminute;{cout<<hour<<z/://<<minute<</,:/z<<sec<
intsec;<endl;}
voidgettime();
為了比較指向數(shù)據(jù)成員和函數(shù)成員的指針。
把數(shù)據(jù)成員也聲明為公有的。一般不要這
么做。
59/145
intmain()
{Timetl(10,13,56);
int*pl=&tl.hour;//定義指向成員的指針pl
cout<<*pl<<endl;
tl.get_time();//調(diào)用成員函數(shù)
Time*p2=&tl;//定義指向?qū)ο髏l的指針p2
p2->get_time();〃用對象指針調(diào)用成員函數(shù)
void(Time::*p3)();71定義指向成員函數(shù)的指針
p3=&Time::gettime;/給成員函數(shù)的指針賦值
(tl.*p3)();//用指向成員函數(shù)的指針調(diào)用成員函數(shù)
retur
,/;1-V,
函數(shù)成員指針的聲明賦值和引用。
60/145
程序運行結(jié)果為:
10〃*pl的值
10:13:56//tl.get_time();的執(zhí)行結(jié)果
10:13:56//p2->get_time();的執(zhí)行結(jié)果
10:13:56//(tl.*p3)();的執(zhí)行結(jié)果
程序采用了三種方法輸出tl的hour,minute,sec的值
說明:
(1)成員函數(shù)的起始地址的正確表示是:
&類名::成員函數(shù)名。
不要寫成:p3=&tl.get_time;
但是寫成:P3=tl.get_time;倒是可以,請思考為什么?
(2)主函數(shù)的第8和9行可以合并寫成:
void(Time::*p3)()=&Time::gettime;
61/145
3.5.3this指針
一個類的成員函數(shù)只有一個內(nèi)存拷貝。類中不論哪個對象調(diào)用
某個成員函數(shù),調(diào)用的都是內(nèi)存中同一個成員函數(shù)代碼。例如
Time類一個成員函數(shù):
voidTime::get_time()
{cout<<hour<<z/:〃:'z<<sec<<endl;}
tl.get_time();
t2.get_time();
當(dāng)不同對象的成員函數(shù)訪問數(shù)據(jù)成員時,怎么保證訪問的就是
指定對象的數(shù)據(jù)成員?
S其實每個成員函數(shù)中都包含一個特殊的指針,它的名字
是thiso它是指向本類對象的指針,
62/145
當(dāng)對象調(diào)用成員函數(shù)時,它的值就是該對象的起始地址。
所以為了區(qū)分不同對象訪問成員函數(shù),語法要求調(diào)用成員
函數(shù)格式是:
intB熨鐮?鷹函數(shù)名(實參表)
從語法搬鮑浦搞錦標(biāo)豳廨用成員函數(shù)。
程悌霆甄印編譯器把對象的地址即this指針放在ECX寄
贛霰麻瞑懿硼口成員函數(shù)定義如下:
{return(this->height*this->width*this->length);}
63/145
對于計算長方體體積的成員函數(shù)volume,當(dāng)對象a調(diào)用它時,
就把對象a地址給this指針,編譯程序?qū)的地址作為實參傳
給成員函數(shù):
a.volume(&a);
函數(shù)體變成:
(this->height)*(this->width)*(this->length)
等價于:(a.height)*(a.width)*(a.length)
C++通過編譯程序,在對象調(diào)用成員函數(shù)時,把對象的地
址賦予this指針,用this指針指向?qū)ο?,實現(xiàn)了用同一
個成員函數(shù)訪問不同對象的數(shù)據(jù)成員。
64/145
可以用(*this)表示調(diào)用成員函數(shù)的對象。
(*this)就是this所指的對象。如前面的計算長方體體積
的函數(shù)中return語句可以寫成:
return((*this).height*(*this).width*(*this).
length);
注意this兩側(cè)的括號不能省略,不能寫成:
return(*this.height**this.width**this.length);
根據(jù)運算符優(yōu)先級語句被翻譯成:*(this,height),而
this.height是非法的,編譯將報錯。
65/145
:
3.1構(gòu)造函數(shù)
3.2析構(gòu)函數(shù)
3.3調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序
3.4對象數(shù)組
3.5對象指針
3.6共用數(shù)據(jù)的保護(hù)
3.7對象的動態(tài)建立和釋放
3.8對象的賦值和復(fù)制
3.9靜態(tài)成員
3.10友元
3.H類模板
66/145
3.6共用數(shù)據(jù)的保護(hù)
如果既希望數(shù)據(jù)在一定范圍內(nèi)共享,又不愿它被隨意修改,
從技術(shù)上可以把數(shù)據(jù)指定為只讀型的。C++提供const手段,
將數(shù)據(jù)、對象、成員函數(shù)指定為常量,從而實現(xiàn)了只讀要
求,達(dá)到保護(hù)數(shù)據(jù)的目的。
67/145
3.6.1常對象
3.6.2常對'象成員
3.6.3指向?qū)ο蟮某V羔?/p>
*3.6.4指向常對象的指針變量
3.6.5對象的常引用
3.6.6const型數(shù)據(jù)小結(jié)
68/145
3.6.1常對象
菽:const類名對象名(實參表);
或:類名const對象名(實參表);
把對象定義為常對象,對象中的數(shù)據(jù)成員就是常變量,在
定義時必須給數(shù)據(jù)成員的初值,因為在程序中不允許修改
常對象的數(shù)據(jù)成員值。
如果常對象的成員函數(shù)不是常成員函數(shù)(除構(gòu)造函數(shù)和析
構(gòu)函數(shù)外),則外界不能調(diào)用此對象的成員函數(shù)。
如:constTime11(10,15,36);
tl.get_time();//錯誤,不能調(diào)用
為了訪問常對象中的數(shù)據(jù)成員,要定義常成員函數(shù):1
voidget_time()const-
即使加上了const,該函觸不能修改對象數(shù)據(jù)成員。
如果在常對象中要修改某個數(shù)據(jù)成員,C++提供了指定可變
的數(shù)據(jù)成員方法。
格式:mutable類型數(shù)據(jù)成員;
在定義數(shù)據(jù)成員時加mutable后,將數(shù)據(jù)成員聲明為可變的
數(shù)據(jù)成員,就可以用聲明為cons珀勺成員函數(shù)修改它的值。
H
70/145
3.6.2常對象成員
可以在聲明普通對象時將數(shù)據(jù)成員或成員函數(shù)聲明為常數(shù)
據(jù)成員或常成員函數(shù)。
71/145
1.常數(shù)據(jù)成員
格式:const類型數(shù)據(jù)成員名
將類中的數(shù)據(jù)成員定義為具有只讀的性質(zhì)。
注意:只能通過帶參數(shù)初始表的構(gòu)造函數(shù)對常數(shù)據(jù)成員進(jìn)
行初始化。
例:constinthour;
Time::Time(inth)
{hour=h;…}〃錯誤
應(yīng)該寫成:
Time::Time(inth):hour
72/145
在類中聲明了某個常數(shù)據(jù)成員后,該類中每個對象的這個
數(shù)據(jù)成員的值都是只讀的,而每個對象的這個數(shù)據(jù)成員的
值可以不同,由定義對象時給出。
73/145
2.常成員函數(shù)
定義格式:
類型函數(shù)名(形參表)const;
const是函數(shù)類型的一部分,在聲明函數(shù)原型和定義函數(shù)
時都要用const關(guān)鍵字。
74/145
使用常成員函數(shù)需注意:
“const是函數(shù)類型的一個組成部分,因此在函數(shù)的實現(xiàn)部分
也要使用關(guān)鍵字ccmsto
0常成員函數(shù)不能修改對象的數(shù)據(jù)成員,也不能調(diào)用該類中
沒有由關(guān)鍵字const修飾的成員函數(shù),從而保證了在常成員
函數(shù)中不會修改數(shù)據(jù)成員的值。
0如果一個對象被說明為常對象,則只能調(diào)用它的常成員函
數(shù)。
般成員函數(shù)可以訪問或修改本類中的非const數(shù)據(jù)成員。而常成員函
數(shù)只能讀本類中的數(shù)據(jù)成員,而不能寫它們。
75/145
成員函數(shù)與成員數(shù)據(jù)的關(guān)系
HIXJ吊數(shù)據(jù)成員.二常函數(shù)成員
:、、/
、、XZ
、t常對象數(shù)據(jù)成員
---------A讀操作實線表示可操作
V--------寫操作虛線表7F不用操作
76/145
常成員函數(shù)小結(jié):
⑴如果類中有部分?jǐn)?shù)據(jù)成員的值要求為只讀,可以將它們
聲明為const,這樣成員函數(shù)只能讀這些數(shù)據(jù)成員的值,但
不能修改它們的值。
⑵如果所有數(shù)據(jù)成員的值為只讀,可將對象聲明為const,
在類中必須聲明const成員函數(shù),常對象只能通過常成員
函數(shù)讀數(shù)據(jù)成員。
⑶常對象不能調(diào)用非const成員函數(shù)。
提醒:如果常對象的成員函數(shù)未加const,編譯系統(tǒng)將其當(dāng)
作非const成員函數(shù);常成員函數(shù)不能調(diào)用非const成員函
■
3
77/145
3.6.3指向?qū)ο蟮某V羔?/p>
如果在定義指向?qū)ο蟮闹羔槙r,使用了關(guān)鍵字const,匕
就是一個常指針,必須在定義時對其初始化。并且在程序
運行中不能再修改指針的值。
類名*const指針變量名二對象地址
例:
Timetl(10,12,15)zt2;
Time*constpl=&tl;
在此后,程序中不能修改Pl。
例:P>&t2;//錯誤語句;
0L
#3
8
百
78/145一
O指向?qū)ο蟮某V羔槪诔绦蜻\行中始終指的是同一個對象。
即指針變量的值始終不變,但它所指對象的數(shù)據(jù)成員值可
以修改。當(dāng)需要將一個指針變量固定地與一個對象相聯(lián)系
時,就可將指針變量指定為const。往往用常指針作為函數(shù)
的形參,目的是不允許在函數(shù)中修改指針變量的值,讓它
始終指向原來的對象。
79/145
364指向常對象的指針變量
格式:
const類型名*指針變量名;
例:constStudent*p;〃指向const對象。
指向?qū)ο?/p>
const非const指針變量
的指針變量
對象
mEconst_^6句指向&可修改
因為const指針變量約束不可指向
比較嚴(yán)格,所以可以指
向任意類型對象。80/145—?可指向&不可修改所
指對象成員
ftinclude<iostream>
ttinclude<string>
usingnamespacestd;
classStudent
{public:
Student(intn,stringnam,chars)
{num=n;
name=nam;
sex-s;
cout<<^Constructorcalled.z/<<num<<endl;}
?Student()
{cout<<z/Destruetorcalled./z<<num<<endl;}
voidsetdata()
{cin>>num;}
voiddisplay()const;
private:
intnum;
voidStudent::display()const
stringname;{cout<<,,num:,,<<num<<endl;
charsex;cout<<,,name:z,<<name<<endl;
);cout〈〈〃sex:,/<<sex<<endl<<endl;
intmain()
{constStudenttl(1,〃yang〃,'f');
Studentt2(2,〃chao〃,'f');
constStudent*p;
Student*q;
p二&tl;〃指向const對象tl的指針變量。
p->display();
p=&t2;〃指向const對象的指針變量可以指向非const對象t2。
p->display();
//q=&tl;〃出錯,指向普通對象的指針變量不可以指向const對象。
//q->display();
q=&t2;〃指向普通對象的指針變量只可以指向普通對象。
q->display();
//p->setdata();通過指向const型的指針變量調(diào)用對象成員函數(shù),無法修
改成員。
//t2.setdata();〃但是通過對象調(diào)用成員函數(shù),則可以修改成員變量。
q->setdata();〃這個也是同樣道理。因為q不是指向常量對象的指針,
所以,可以調(diào)用能夠修改成員變量的函數(shù)。
return0;
82/145
3.6.5對象的常引用
前面學(xué)過引用是傳遞參數(shù)的有效辦法。用引用形參時,形
參變量與實參變量是同一個變量,在函數(shù)內(nèi)修改引用形參
也就是修改實參變量。
如果用引用形參又不想讓函數(shù)修改實參,可以使用常引用
機(jī)制。
格式:const類名&形參對象名
如:constStudent&stu
83/145
例3.8對象的引用
ttinclude<iostream>voidTime::gettime()
usingnamespacestd;(
classTimecout<<hour;
{public:cout<<minute;
Time(int,int,int);cout<<sec;
voidsettime();
voidgettime();
voidTime::settime()
private:(
inthour;cin>>hour;
intminute;cin>>minute;
intsec;cin>>sec;
);
Time::Time(inth,intm,ints)
{hour=h;
minute=m;
SeC=S;}84/145
voidfun(Time&t)//引用型形參,如果參數(shù)前面加
const,則不能修改所引用對象的成員數(shù)據(jù)。
{t.settime();
)
intmain()
{Timetl(10,13,56);
tl.gettime();
fun(tl);〃傳遞對象的地址
tl.gettime();
return0;
85/145
3.6.6const型數(shù)據(jù)的小結(jié)企
表3.3
形式含義
Timeconsttl;
tl是常對象,其值在任何情況下都不能改變
或constTimetl;
voidTime::fun()constfun是Time類中的常成員函數(shù),可以引用,但不能修改本類中的數(shù)據(jù)成員
Time*constp;P是指向Time對象的常指針,p的值(即p的指向)不能改變
constTime*p;P是指向Time類常對象的指針,其指向的類對象的值不能通過指針來改變
Time&tl=t;tl是Time類對象t的引用,t和tl指向同一段內(nèi)存空間
訣竅:從變量開始往左推導(dǎo),即可得知一個變量是什么類型的。星號左邊是
要指向的東西,右邊都是修飾指針變量的。如:
Time*constp;p左邊是const的,表示p不能變,再往左是星號,說明p
是一個指針,再往左是類名,表示指向那樣一個類的對象,成員可以修改。
Timeconst*p;p左邊是星號,表示p是一個指針,指向的東西是const的,
不能變的,再往左是類名,表示指向那樣一個類的對象,其成員不能修改。
O0/T40
3.1構(gòu)造函數(shù)
3.2析構(gòu)函數(shù)
3.3調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的順序
3.4對象數(shù)組
3.5對象指針
3.6共用數(shù)據(jù)的保護(hù)
3.7對象的動態(tài)建立和釋放
3.8對象的賦值和復(fù)制
3.9靜態(tài)成員
3.10友元
2
3.n類模板/8?
£
8
f艮
87/145-一
3.7對象的動態(tài)建立和釋放
0C++提供了new和delete運算符,實現(xiàn)動態(tài)分配、回收內(nèi)存。它們也可以
用來動態(tài)建立對象和釋放對象。
1.動態(tài)建立對象格式:new類名;
功能:在堆里分配內(nèi)存,建立指定類的一個無名對象。
如果分配成功,將返回動態(tài)對象的起始地址(指針);
如不成功,返回0。為了保存這個指針,必須事先定義
類類型的指針變量。
格式:類名*指針變量名;
例:Box*pt;
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年環(huán)境保護(hù)知識環(huán)境監(jiān)測與治理技術(shù)模擬題
- 2026年京東技術(shù)面試題及答案詳解
- 2025年企業(yè)產(chǎn)品水足跡標(biāo)簽申請代理合同
- 2025年管轄權(quán)異議申請書(被告提交)
- 《JBT 14674-2024風(fēng)力發(fā)電機(jī)組 變槳齒輪箱》專題研究報告
- 檢驗科實驗室廢水的處理制度及流程
- 2025年三臺縣幼兒園教師招教考試備考題庫含答案解析(必刷)
- 2025年黎城縣招教考試備考題庫帶答案解析(必刷)
- 2024年西雙版納職業(yè)技術(shù)學(xué)院馬克思主義基本原理概論期末考試題附答案解析(奪冠)
- 2025年西豐縣幼兒園教師招教考試備考題庫附答案解析(必刷)
- 人教版(2024)七年級上冊數(shù)學(xué)期末綜合檢測試卷 3套(含答案)
- 研發(fā)資料規(guī)范管理制度(3篇)
- GB/T 16770.1-2025整體硬質(zhì)合金直柄立銑刀第1部分:型式與尺寸
- 工業(yè)產(chǎn)品銷售單位質(zhì)量安全日管控周排查月調(diào)度檢查記錄表
- 2025年風(fēng)險管理自查報告
- 2026年中國煤炭資源行業(yè)投資前景分析研究報告
- 項目成本控制動態(tài)監(jiān)測表模板
- DBJ46-074-2025 海南省市政道路瀝青路面建設(shè)技術(shù)標(biāo)準(zhǔn)
- 幼兒園小班語言《大一歲了》課件
- GB/T 14071-2025林木品種審定規(guī)范
- 移風(fēng)易俗問答題目及答案
評論
0/150
提交評論