第三章關(guān)于類和對象_第1頁
第三章關(guān)于類和對象_第2頁
第三章關(guān)于類和對象_第3頁
第三章關(guān)于類和對象_第4頁
第三章關(guān)于類和對象_第5頁
已閱讀5頁,還剩140頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論