計(jì)算機(jī)二級C++考試復(fù)習(xí)資料(全)_第1頁
計(jì)算機(jī)二級C++考試復(fù)習(xí)資料(全)_第2頁
計(jì)算機(jī)二級C++考試復(fù)習(xí)資料(全)_第3頁
計(jì)算機(jī)二級C++考試復(fù)習(xí)資料(全)_第4頁
計(jì)算機(jī)二級C++考試復(fù)習(xí)資料(全)_第5頁
已閱讀5頁,還剩104頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

------------------------------------------------------------------------計(jì)算機(jī)二級C++考試復(fù)習(xí)資料(全)計(jì)算機(jī)二級C++考試復(fù)習(xí)資料(全)一、C++概述(一)發(fā)展歷史1980年,BjarneStroustrup博士開始著手創(chuàng)建一種模擬語言,能夠具有面向?qū)ο蟮某绦蛟O(shè)計(jì)特色。在當(dāng)時,面向?qū)ο缶幊踢€是一個比較新的理念,Stroustrup博士并不是從頭開始設(shè)計(jì)新語言,而是在C語言的基礎(chǔ)上進(jìn)行創(chuàng)建。這就是C++語言。

1985年,C++開始在外面慢慢流行。經(jīng)過多年的發(fā)展,C++已經(jīng)有了多個版本。為次,ANSI和ISO的聯(lián)合委員會于1989年著手為C++制定標(biāo)準(zhǔn)。1994年2月,該委員會出版了第一份非正式草案,1998年正式推出了C++的國際標(biāo)準(zhǔn)。

(二)C和C++

C++是C的超集,也可以說C是C++的子集,因?yàn)镃先出現(xiàn)。按常理說,C++編譯器能夠編譯任何C程序,但是C和C++還是有一些小差別。

例如C++增加了C不具有的關(guān)鍵字。這些關(guān)鍵字能作為函數(shù)和變量的標(biāo)識符在C程序中使用,盡管C++包含了所有的C,但顯然沒有任何C++編譯器能編譯這樣的C程序。

C程序員可以省略函數(shù)原型,而C++不可以,一個不帶參數(shù)的C函數(shù)原型必須把void寫出來。而C++可以使用空參數(shù)列表。

C++中new和delete是對內(nèi)存分配的運(yùn)算符,取代了C中的malloc和free。

標(biāo)準(zhǔn)C++中的字符串類取代了C標(biāo)準(zhǔn)C函數(shù)庫頭文件中的字符數(shù)組處理函數(shù)。

C++中用來做控制態(tài)輸入輸出的iostream類庫替代了標(biāo)準(zhǔn)C中的stdio函數(shù)庫。

C++中的try/catch/throw異常處理機(jī)制取代了標(biāo)準(zhǔn)C中的setjmp()和longjmp()函數(shù)。

二、關(guān)鍵字和變量

C++相對與C增加了一些關(guān)鍵字,如下:

typenamebooldynamic_castmutablenamespace

static_castusingcatchexplicitnew

virtualoperatorfalseprivatetemplate

volatileconstprotectedthiswchar_t

const_castpublicthrowfriendtrue

reinterpret_casttry

bitorxor_eand_eqcomplor_eq

not_eqbitand

在C++中還增加了bool型變量和wchar_t型變量:

布爾型變量是有兩種邏輯狀態(tài)的變量,它包含兩個值:真和假。如果在表達(dá)式中使用了布爾型變量,那么將根據(jù)變量值的真假而賦予整型值1或0。要把一個整型變量轉(zhuǎn)換成布爾型變量,如果整型值為0,則其布爾型值為假;反之如果整型值為非0,則其布爾型值為真。布兒型變量在運(yùn)行時通常用做標(biāo)志,比如進(jìn)行邏輯測試以改變程序流程。

#includeiostream.h

intmain()

{

boolflag;

flag=true;

if(flag)cout<return0;

}

C++中還包括wchar_t數(shù)據(jù)類型,wchar_t也是字符類型,但是是那些寬度超過8位的數(shù)據(jù)類型。許多外文字符集所含的數(shù)目超過256個,char字符類型無法完全囊括。wchar_t數(shù)據(jù)類型一般為16位。

標(biāo)準(zhǔn)C++的iostream類庫中包括了可以支持寬字符的類和對象。用wout替代cout即可。

#includeiostream.h

intmain()

{

wchar_twc;

wc='b';

wout<wc='y';

wout<wc='e';

wout<return0;

}

說明一下:某些編譯器無法編譯該程序(不支持該數(shù)據(jù)類型)。

三、強(qiáng)制類型轉(zhuǎn)換

有時候,根據(jù)表達(dá)式的需要,某個數(shù)據(jù)需要被當(dāng)成另外的數(shù)據(jù)類型來處理,這時,就需要強(qiáng)制編譯器把變量或常數(shù)由聲明時的類型轉(zhuǎn)換成需要的類型。為此,就要使用強(qiáng)制類型轉(zhuǎn)換說明,格式如下:

int*iptr=(int*)&table;

表達(dá)式的前綴(int*)就是傳統(tǒng)C風(fēng)格的強(qiáng)制類型轉(zhuǎn)換說明(typecast),又可稱為強(qiáng)制轉(zhuǎn)換說明(cast)。強(qiáng)制轉(zhuǎn)換說明告訴編譯器把表達(dá)式轉(zhuǎn)換成指定的類型。有些情況下強(qiáng)制轉(zhuǎn)換是禁用的,例如不能把一個結(jié)構(gòu)類型轉(zhuǎn)換成其他任何類型。數(shù)字類型和數(shù)字類型、指針和指針之間可以相互轉(zhuǎn)換。當(dāng)然,數(shù)字類型和指針類型也可以相互轉(zhuǎn)換,但通常認(rèn)為這樣做是不安全而且也是沒必要的。強(qiáng)制類型轉(zhuǎn)換可以避免編譯器的警告。

longintel=123;

shorti=(int)el;

floatm=34.56;

inti=(int)m;

上面兩個都是C風(fēng)格的強(qiáng)制類型轉(zhuǎn)換,C++還增加了一種轉(zhuǎn)換方式,比較一下上面和下面這個書寫方式的不同:

longintel=123;

shorti=int(el);

floatm=34.56;

inti=int(m);

使用強(qiáng)制類型轉(zhuǎn)換的最大好處就是:禁止編譯器對你故意去做的事發(fā)出警告。但是,利用強(qiáng)制類型轉(zhuǎn)換說明使得編譯器的類型檢查機(jī)制失效,這不是明智的選擇。通常,是不提倡進(jìn)行強(qiáng)制類型轉(zhuǎn)換的。除非不可避免,如要調(diào)用malloc()函數(shù)時要用的void型指針轉(zhuǎn)換成指定類型指針。

四、標(biāo)準(zhǔn)輸入輸出流

在C語言中,輸入輸出是使用語句scanf()和printf()來實(shí)現(xiàn)的,而C++中是使用類來實(shí)現(xiàn)的。

#includeiostream.h

main()//C++中main()函數(shù)默認(rèn)為int型,而C語言中默認(rèn)為void型。

{

inta;

cout<

cin>>a;/*輸入一個數(shù)值*/

cout<return0;

}

cin,cout,endl對象,他們本身并不是C++語言的組成部分。雖然他們已經(jīng)是ANSI標(biāo)準(zhǔn)C++中被定義,但是他們不是語言的內(nèi)在組成部分。在C++中不提供內(nèi)在的輸入輸出運(yùn)算符,這與其他語言是不同的。輸入和輸出是通過C++類來實(shí)現(xiàn)的,cin和cout是這些類的實(shí)例,他們是在C++語言的外部實(shí)現(xiàn)。

在C++語言中,有了一種新的注釋方法,就是‘//’,在該行//后的所有說明都被編譯器認(rèn)為是注釋,這種注釋不能換行。C++中仍然保留了傳統(tǒng)C語言的注釋風(fēng)格/*……*/。

C++也可采用格式化輸出的方法:

#includeiostream.h

intmain()

{

inta;

cout<

cin>>a;

cout<

五、函數(shù)重載

在C++中,允許有相同的函數(shù)名,不過它們的參數(shù)類型不能完全相同,這樣這些函數(shù)就可以相互區(qū)別開來。而這在C語言中是不允許的。

1.參數(shù)個數(shù)不同

#includeiostream.h

voida(int,int);

voida(int);

intmain()

{

a(5);

a(6,7);

return0;

}

voida(inti)

{

cout<}

voida(inti,intj)

{

cout<}

2.參數(shù)格式不同

#includeiostream.h

voida(int,int);

voida(int,float);

intmain()

{

a(5,6);

a(6,7.0);

return0;

}

voida(inti,intj)

{

cout<}

voida(inti,floatj)

{

cout<}

六、變量作用域

C++語言中,允許變量定義語句在程序中的任何地方,只要在是使用它之前就可以;而C語言中,必須要在函數(shù)開頭部分。而且C++允許重復(fù)定義變量,C語言也是做不到這一點(diǎn)的。看下面的程序:

#includeiostream.h

inta;

intmain()

{

cin>>a;

for(inti=1;i<=10;i++)//C語言中,不允許在這里定義變量

{

staticinta=0;//C語言中,同一函數(shù)塊,不允許有同名變量

a+=i;

cout<<::a<<<}

return0;

}七、new和delete運(yùn)算符

在C++語言中,仍然支持malloc()和free()來分配和釋放內(nèi)存,同時增加了new和delete來管理內(nèi)存。

1.為固定大小的數(shù)組分配內(nèi)存

#includeiostream.h

intmain()

{

int*birthday=newint[3];

birthday[0]=6;

birthday[1]=24;

birthday[2]=1940;

cout<<delete[]birthday;//注意這兒

return0;

}

在刪除數(shù)組時,delete運(yùn)算符后要有一對方括號。

2.為動態(tài)數(shù)組分配內(nèi)存

#includeiostream.h

#includestdlib.h

intmain()

{

intsize;

cin>>size;

int*array=newint[size];

for(inti=0;iarray[i]=rand();

for(i=0;icout<<'\n'<delete[]array;

return0;

}

八、引用型變量

在C++中,引用是一個經(jīng)常使用的概念。引用型變量是其他變量的一個別名,我們可以認(rèn)為他們只是名字不相同,其他都是相同的。

1.引用是一個別名

C++中的引用是其他變量的別名。聲明一個引用型變量,需要給他一個初始化值,在變量的生存周期內(nèi),該值不會改變。&運(yùn)算符定義了一個引用型變量:

inta;

int&b=a;

先聲明一個名為a的變量,它還有一個別名b。我們可以認(rèn)為是一個人,有一個真名,一個外號,以后不管是喊他a還是b,都是叫他這個人。同樣,作為變量,以后對這兩個標(biāo)識符操作都會產(chǎn)生相同的效果。

#includeiostream.h

intmain()

{

inta=123;

int&b=a;

cout<a++;

cout<b++;

cout<return0;

}

2.引用的初始化

和指針不同,引用變量的值不可改變。引用作為真實(shí)對象的別名,必須進(jìn)行初始化,除非滿足下列條件之一:

(1)引用變量被聲明為外部的,它可以在任何地方初始化

(2)引用變量作為類的成員,在構(gòu)造函數(shù)里對它進(jìn)行初始化

(3)引用變量作為函數(shù)聲明的形參,在函數(shù)調(diào)用時,用調(diào)用者的實(shí)參來進(jìn)行初始化

3.作為函數(shù)形參的引用

引用常常被用作函數(shù)的形參。以引用代替拷貝作為形參的優(yōu)點(diǎn):

引用避免了傳遞大型數(shù)據(jù)結(jié)構(gòu)帶來的額外開銷

引用無須象指針那樣需要使用*和->等運(yùn)算符

#includeiostream.h

voidfunc1(sp);

voidfunc2(s&p);

structs

{

intn;

chartext[10];

};

intmain()

{

staticsstr={123,China};

func1(str);

func2(str);

return0;

}

voidfunc1(sp)

{

cout<cout<}

voidfunc2(s&p)

{

cout<cout<}

從表面上看,這兩個函數(shù)沒有明顯區(qū)別,不過他們所花的時間卻有很大差異,func2()函數(shù)所用的時間開銷會比func2()函數(shù)少很多。它們還有一個差別,如果程序遞歸func1(),隨著遞歸的深入,會因?yàn)闂5暮谋M而崩潰,但func2()沒有這樣的擔(dān)憂。

4.以引用方式調(diào)用

當(dāng)函數(shù)把引用作為參數(shù)傳遞給另一個函數(shù)時,被調(diào)用函數(shù)將直接對參數(shù)在調(diào)用者中的拷貝進(jìn)行操作,而不是產(chǎn)生一個局部的拷貝(傳遞變量本身是這樣的)。這就稱為以引用方式調(diào)用。把參數(shù)的值傳遞到被調(diào)用函數(shù)內(nèi)部的拷貝中則稱為以傳值方式調(diào)用。

#includeiostream.h

voiddisplay(constDate&,constchar*);

voidswapper(Date&,Date&);

structDate

{

intmonth,day,year;

};

intmain()

{

staticDatenow={2,23,90};

staticDatethen={9,10,60};

display(now,Now:);

display(then,Then:);

swapper(now,then);

display(now,Now:);

display(then,Then:);

return0;

}

voidswapper(Date&dt1,Date&dt2)

{

Datesave;

save=dt1;

dt1=dt2;

dt2=save;

}

voiddisplay(constDate&dt,constchar*s)

{

cout<cout<}

5.以引用作為返回值

#includeiostream.h

structDate

{

intmonth,day,year;

};

Datebirthdays[]=

{

{12,12,60};

{10,25,85};

{5,20,73};

};

constDate&getdate(intn)

{

returnbirthdays[n-1];

}

intmain()

{

intdt=1;

while(dt!=0)

{

cout<cin>>dt;

if(dt>0&&dt<4)

{

constDate&bd=getdate(dt);

cout<}

}

return0;

}

程序都很簡單,就不講解了C++輔導(dǎo)筆記:類的設(shè)計(jì)、構(gòu)造函數(shù)和析構(gòu)函數(shù)一、類的設(shè)計(jì)

1.類的聲明

class類名

{

private://私有

...

public://公有

...

};

2.類的成員

一般在C++類中,所有定義的變量和函數(shù)都是類的成員。如果是變量,我們就叫它數(shù)據(jù)成員如果是函數(shù),我們就叫它成員函數(shù)。

3.類成員的可見性

private和public訪問控制符決定了成員的可見性。由一個訪問控制符設(shè)定的可訪問狀態(tài)將一直持續(xù)到下一個訪問控制符出現(xiàn),或者類聲明的結(jié)束。私有成員僅能被同一個類中的成員函數(shù)訪問,公有成員既可以被同一類中的成員函數(shù)訪問,也可以被其他已經(jīng)實(shí)例化的類中函數(shù)訪問。當(dāng)然,這也有例外的情況,這是以后要討論的友元函數(shù)。

類中默認(rèn)的數(shù)據(jù)類型是private,結(jié)構(gòu)中的默認(rèn)類型是public。一般情況下,變量都作為私有成員出現(xiàn),函數(shù)都作為公有成員出現(xiàn)。

類中還有一種訪問控制符protected,叫保護(hù)成員,以后再說明。

4.初始化

在聲明一個類的對象時,可以用圓括號()包含一個初始化表。

看下面一個例子:

#includeiostream.h

classBox

{

private:

intheight,width,depth;//3個私有數(shù)據(jù)成員

public:

Box(int,int,int);

~Box();

intvolume();//成員函數(shù)

};

Box::Box(intht,intwd,intdp)

{

height=ht;

width=wd;

depth=dp;

}

Box::~Box()

{

//nothing

}

intBox::volume()

{

returnheight*width*depth;

}

intmain()

{

Boxthisbox(3,4,5);//聲明一個類對象并初始化

cout<return0;

}

當(dāng)一個類中沒有private成員和protected成員時,也沒有虛函數(shù),并且不是從其他類中派生出來的,可以用{}來初始化。(以后再講解)

5.內(nèi)聯(lián)函數(shù)

內(nèi)聯(lián)函數(shù)和普通函數(shù)的區(qū)別是:內(nèi)聯(lián)函數(shù)是在編譯過程中展開的。通常內(nèi)聯(lián)函數(shù)必須簡短。定義類的內(nèi)聯(lián)函數(shù)有兩種方法:一種和C語言一樣,在定義函數(shù)時使用關(guān)鍵字inline。如:

inlineintBox::volume()

{

returnheight*width*depth;

}

還有一種方法就是直接在類聲明的內(nèi)部定義函數(shù)體,而不是僅僅給出一個函數(shù)原型。我們把上面的函數(shù)簡化一下:

#includeiostream.h

classBox

{

private:

intheight,width,depth;

public:

Box(intht,intwd,intdp)

{

height=ht;

width=wd;

depth=dp;

}

~Box();

intvolume()

{

returnheight*width*depth;

}

};

intmain()

{

Boxthisbox(3,4,5);//聲明一個類對象并初始化

cout<return0;

}

這樣,兩個函數(shù)都默認(rèn)為內(nèi)聯(lián)函數(shù)了。二、構(gòu)造函數(shù)

什么是構(gòu)造函數(shù)?通俗的講,在類中,函數(shù)名和類名相同的函數(shù)稱為構(gòu)造函數(shù)。上面的Box()函數(shù)就是構(gòu)造函數(shù)。C++允許同名函數(shù),也就允許在一個類中有多個構(gòu)造函數(shù)。如果一個都沒有,編譯器將為該類產(chǎn)生一個默認(rèn)的構(gòu)造函數(shù),這個構(gòu)造函數(shù)可能會完成一些工作,也可能什么都不做。

絕對不能指定構(gòu)造函數(shù)的類型,即使是void型都不可以。實(shí)際上構(gòu)造函數(shù)默認(rèn)為void型。

當(dāng)一個類的對象進(jìn)入作用域時,系統(tǒng)會為其數(shù)據(jù)成員分配足夠的內(nèi)存,但是系統(tǒng)不一定將其初始化。和內(nèi)部數(shù)據(jù)類型對象一樣,外部對象的數(shù)據(jù)成員總是初始化為0。局部對象不會被初始化。構(gòu)造函數(shù)就是被用來進(jìn)行初始化工作的。當(dāng)自動類型的類對象離開其作用域時,所站用的內(nèi)存將釋放回系統(tǒng)。

看上面的例子,構(gòu)造函數(shù)Box()函數(shù)接受三個整型擦黑素,并把他們賦值給立方體對象的數(shù)據(jù)成員。

如果構(gòu)造函數(shù)沒有參數(shù),那么聲明對象時也不需要括號。

1.使用默認(rèn)參數(shù)的構(gòu)造函數(shù)

當(dāng)在聲明類對象時,如果沒有指定參數(shù),則使用默認(rèn)參數(shù)來初始化對象。

#includeiostream.h

classBox

{

private:

intheight,width,depth;

public:

Box(intht=2,intwd=3,intdp=4)

{

height=ht;

width=wd;

depth=dp;

}

~Box();

intvolume()

{

returnheight*width*depth;

}

};

intmain()

{

Boxthisbox(3,4,5);//初始化

Boxdefaulbox;//使用默認(rèn)參數(shù)

cout<cout<

return0;

}

2.默認(rèn)構(gòu)造函數(shù)

沒有參數(shù)或者參數(shù)都是默認(rèn)值的構(gòu)造函數(shù)稱為默認(rèn)構(gòu)造函數(shù)。如果你不提供構(gòu)造函數(shù),編譯器會自動產(chǎn)生一個公共的默認(rèn)構(gòu)造函數(shù),這個構(gòu)造函數(shù)什么都不做。如果至少提供一個構(gòu)造函數(shù),則編譯器就不會產(chǎn)生默認(rèn)構(gòu)造函數(shù)。

3.重載構(gòu)造函數(shù)

一個類中可以有多個構(gòu)造函數(shù)。這些構(gòu)造函數(shù)必須具有不同的參數(shù)表。在一個類中需要接受不同初始化值時,就需要編寫多個構(gòu)造函數(shù),但有時候只需要一個不帶初始值的空的Box對象。

#includeiostream.h

classBox

{

private:

intheight,width,depth;

public:

Box(){//nothing}

Box(intht=2,intwd=3,intdp=4)

{

height=ht;

width=wd;

depth=dp;

}

~Box();

intvolume()

{

returnheight*width*depth;

}

};

intmain()

{

Boxthisbox(3,4,5);//初始化

Boxotherbox;

otherbox=thisbox;

cout<return0;

}

這兩個構(gòu)造函數(shù)一個沒有初始化值,一個有。當(dāng)沒有初始化值時,程序使用默認(rèn)值,即2,3,4。

但是這樣的程序是不好的。它允許使用初始化過的和沒有初始化過的Box對象,但它沒有考慮當(dāng)thisbox給otherbox賦值失敗后,volume()該返回什么。較好的方法是,沒有參數(shù)表的構(gòu)造函數(shù)也把默認(rèn)值賦值給對象。

classBox

{

intheight,width,depth;

public:

Box()

{

height=0;width=0;depth=0;

}

Box(intht,intwd,intdp)

{

height=ht;width=wd;depth=dp;

}

intvolume()

{

returnheight*width*depth;

}

};

這還不是最好的方法,更好的方法是使用默認(rèn)參數(shù),根本不需要不帶參數(shù)的構(gòu)造函數(shù)。

classBox

{

intheight,width,depth;

public:

Box(intht=0,intwd=0,intdp=0)

{

height=ht;width=wd;depth=dp;

}

intvolume()

{

returnheight*width*depth;

}

};

三、析構(gòu)函數(shù)

當(dāng)一個類的對象離開作用域時,析構(gòu)函數(shù)將被調(diào)用(系統(tǒng)自動調(diào)用)。析構(gòu)函數(shù)的名字和類名一樣,不過要在前面加上~。對一個類來說,只能允許一個析構(gòu)函數(shù),析構(gòu)函數(shù)不能有參數(shù),并且也沒有返回值。析構(gòu)函數(shù)的作用是完成一個清理工作,如釋放從堆中分配的內(nèi)存。

我們也可以只給出析構(gòu)函數(shù)的形式,而不給出起具體函數(shù)體,其效果是一樣的,如上面的例子。但在有些情況下,析構(gòu)函數(shù)又是必需的。如在類中從堆中分配了內(nèi)存,則必須在析構(gòu)函數(shù)中釋放二級C++輔導(dǎo)筆記:類的轉(zhuǎn)換C++的內(nèi)部數(shù)據(jù)類型遵循隱式類型轉(zhuǎn)換規(guī)則。假設(shè)某個表達(dá)市中使用了一個短整型變量,而編譯器根據(jù)上下文認(rèn)為這兒需要是的長整型,則編譯器就會根據(jù)類型轉(zhuǎn)換規(guī)則自動把它轉(zhuǎn)換成長整型,這種隱式轉(zhuǎn)換出現(xiàn)在賦值、參數(shù)傳遞、返回值、初始化和表達(dá)式中。我們也可以為類提供相應(yīng)的轉(zhuǎn)換規(guī)則。

對一個類建立隱式轉(zhuǎn)換規(guī)則需要構(gòu)造一個轉(zhuǎn)換函數(shù),該函數(shù)作為類的成員,可以把該類的對象和其他數(shù)據(jù)類型的對象進(jìn)行相互轉(zhuǎn)換。聲明了轉(zhuǎn)換函數(shù),就告訴了編譯器,當(dāng)根據(jù)句法判定需要類型轉(zhuǎn)換時,就調(diào)用函數(shù)。

有兩種轉(zhuǎn)換函數(shù)。一種是轉(zhuǎn)換構(gòu)造函數(shù);另一種是成員轉(zhuǎn)換函數(shù)。需要采用哪種轉(zhuǎn)換函數(shù)取決于轉(zhuǎn)換的方向。

一、轉(zhuǎn)換構(gòu)造函數(shù)

當(dāng)一個構(gòu)造函數(shù)僅有一個參數(shù),且該參數(shù)是不同于該類的一個數(shù)據(jù)類型,這樣的構(gòu)造函數(shù)就叫轉(zhuǎn)換構(gòu)造函數(shù)。轉(zhuǎn)換構(gòu)造函數(shù)把別的數(shù)據(jù)類型的對象轉(zhuǎn)換為該類的一個對象。和其他構(gòu)造函數(shù)一樣,如果聲明類的對象的初始化表同轉(zhuǎn)換構(gòu)造函數(shù)的參數(shù)表相匹配,該函數(shù)就會被調(diào)用。當(dāng)在需要使用該類的地方使用了別的數(shù)據(jù)類型,便宜器就會調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)進(jìn)行轉(zhuǎn)換。

#includeiostream.h

#includetime.h

#includestdio.h

classDate

{

intmo,da,yr;

public:

Date(time_t);

voiddisplay();

};

voidDate::display()

{

charyear[5];

if(yr<10)

sprintf(year,0%d,yr);

else

sprintf(year,%d,yr);

cout<}

Date::Date(time_tnow)

{

tm*tim=localtime(&now);

da=tim->tm_mday;

mo=tim->tm_mon+1;

yr=tim->tm_year;

if(yr>=100)yr-=100;

}

intmain()

{

time_tnow=time(0);

Datedt(now);

dt.display();

return0;

}

本程序先調(diào)用time()函數(shù)來獲取當(dāng)前時間,并把它賦給time_t對象;然后程序通過調(diào)用Date類的轉(zhuǎn)換構(gòu)造函數(shù)來創(chuàng)建一個Date對象,該對象由time_t對象轉(zhuǎn)換而來。time_t對象先傳遞給localtime()函數(shù),然后返回一個指向tm結(jié)構(gòu)(time.h文件中聲明)的指針,然后構(gòu)造函數(shù)把結(jié)構(gòu)中的日月年的數(shù)值拷貝給Date對象的數(shù)據(jù)成員,這就完成了從time_t對象到Date對象的轉(zhuǎn)換。

二、成員轉(zhuǎn)換函數(shù)

成員轉(zhuǎn)換函數(shù)把該類的對象轉(zhuǎn)換為其他數(shù)據(jù)類型的對象。在成員轉(zhuǎn)換函數(shù)的聲明中要用到關(guān)鍵字operator。這樣聲明一個成員轉(zhuǎn)換函數(shù):

operatoraaa();

在這個例子中,aaa就是要轉(zhuǎn)換成的數(shù)據(jù)類型的說明符。這里的類型說明符可以是任何合法的C++類型,包括其他的類。如下來定義成員轉(zhuǎn)換函數(shù);

Classname::operatoraaa()

類名標(biāo)識符是聲明了該函數(shù)的類的類型說明符。上面定義的Date類并不能把該類的對象轉(zhuǎn)換回time_t型變量,但可以把它轉(zhuǎn)換成一個長整型值,計(jì)算從2000年1月1日到現(xiàn)在的天數(shù)。

#includeiostream.h

classDate

{

intmo,da,yr;

public:

Date(intm,intd,inty){mo=m;da=d;yr=y;}

operatorint();//聲明

};

Date::operatorint()//定義

{

staticintdys[]={31,28,31,30,31,30,31,31,30,31,30,31};

intdays=yr-2000;

days*=365;

days+=(yr-2000)/4;

for(inti=0;idays+=dys[i];

days+=da;

returndays;

}

intmain()

{

Datenow(12,24,2003);

intsince=now;

cout<return0;

}

三、類的轉(zhuǎn)換

上面兩個例子都是C++類對象和內(nèi)部數(shù)據(jù)對象之間的相互轉(zhuǎn)換。也可以定義轉(zhuǎn)換函數(shù)來實(shí)現(xiàn)兩個類對象之間的相互轉(zhuǎn)換。

#includeiostream.h

classCustomDate

{

public:

intda,yr;

CustomDate(intd=0,inty=0){da=d;yr=y;}

voiddisplay()

{

cout<}

};

classDate

{

intmo,da,yr;

public:

Date(intm=0,intd=0,inty=0){mo=m;da=d;yr=y;}

Date(constCustomDate&);//轉(zhuǎn)換構(gòu)造函數(shù)

operatorCustomDate();//成員轉(zhuǎn)換函數(shù)

voiddisplay()

{

cout<}

};

staticintdys[]={31,28,31,30,31,30,31,31,30,31,30,31};

Date::Date(constCustomDate&jd)

{

yr=jd.yr;

da=jd.da;

for(mo=0;mo<11;mo++)

if(da>dys[mo])da-=dys[mo];

elsebreak;

mo++;

}

Date::operatorCustomDate()

{

CustomDatecd(0,yr);

for(inti=0;icd.da+=da;

returncd;

}

intmain()

{

Datedt(12,24,3);

CustomDatecd;

cd=dt;//調(diào)用成員轉(zhuǎn)換函數(shù)

cd.display();

dt=cd;//調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)

dt.display();

return0;

}

這個例子中有兩個類CustomDate和Date,CustomDate型日期包含年份和天數(shù)。

這個例子沒有考慮閏年情況。但是在實(shí)際構(gòu)造一個類時,應(yīng)該考慮到所有問題的可能性。

在Date里中具有兩種轉(zhuǎn)換函數(shù),這樣,當(dāng)需要從Date型變?yōu)镃ustomDate型十,可以調(diào)用成員轉(zhuǎn)換函數(shù);反之可以調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)。

不能既在Date類中定義成員轉(zhuǎn)換函數(shù),又在CustomDate類里定義轉(zhuǎn)換構(gòu)造函數(shù)。那樣編譯器在進(jìn)行轉(zhuǎn)換時就不知道該調(diào)用哪一個函數(shù),從而出錯.四、轉(zhuǎn)換函數(shù)的調(diào)用

C++里調(diào)用轉(zhuǎn)換函數(shù)有三種形式:第一種是隱式轉(zhuǎn)換,例如編譯器需要一個Date對象,而程序提供的是CustomDate對象,編譯器會自動調(diào)用合適的轉(zhuǎn)換函數(shù)。另外兩種都是需要在程序代碼中明確給出的顯式轉(zhuǎn)換。C++強(qiáng)制類型轉(zhuǎn)換是一種,還有一種是顯式調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)和成員轉(zhuǎn)換函數(shù)。下面的程序給出了三中轉(zhuǎn)換形式:

#includeiostream.h

classCustomDate

{

public:

intda,yr;

CustomDate(intd=0,inty=0){da=d;yr=y;}

voiddisplay()

{

cout<}

};

classDate

{

intmo,da,yr;

public:

Date(intm,intd,inty)

{

mo=m;da=d;yr=y;

}

operatorCustomDate();

};

Date::operatorCustomDate()

{

staticintdys[]={31,28,31,30,31,30,31,31,30,31,30,31};

CustomDatecd(0,yr);

for(inti=0;icd.da+=da;

returncd;

}

intmain()

{

Datedt(11,17,89);

CustomDatecd;

cd=dt;

cd.display();

cd=(CustomDate)dt;

cd.display();

cd=CustomDate(dt);

cd.display();

return0;

}

五、轉(zhuǎn)換發(fā)生的情形

上面的幾個例子都是通過不能類型對象之間的相互賦值來調(diào)用轉(zhuǎn)換函數(shù),還有幾種調(diào)用的可能:

參數(shù)傳遞

初始化

返回值

表達(dá)式語句

這些情況下,都有可能調(diào)用轉(zhuǎn)換函數(shù)。

下面的程序不難理解,就不分析了。

#includeiostream.h

classCustomDate

{

public:

intda,yr;

CustomDate(){}

CustomDate(intd,inty){da=d;yr=y;}

voiddisplay()

{

cout<}

};

classDate

{

intmo,da,yr;

public:

Date(intm,intd,inty){mo=m;da=d;yr=y;}

operatorCustomDate();

};

Date::operatorCustomDate()

{

staticintdys[]={31,28,31,30,31,30,31,31,30,31,30,31};

CustomDatecd(0,yr);

for(inti=0;icd.da+=da;

returncd;

}

classTester

{

CustomDatecd;

public:

explicitTester(CustomDatec){cd=c;}

voiddisplay(){cd.display();}

};

voiddispdate(CustomDatecd)

{

cd.display();

}

CustomDatertndate()

{

Datedt(9,11,1);

returndt;

}

intmain()

{

Datedt(12,24,3);

CustomDatecd;

cd=dt;

cd.display();

dispdate(dt);

Testerts(dt);

ts.display();

cd=rtndate();

cd.display();

return0;

}

六、顯式構(gòu)造函數(shù)

注意上面Tester類的構(gòu)造函數(shù)前面有一個explicit修飾符。如果不加上這個關(guān)鍵字,那么在需要把CustomDate對象轉(zhuǎn)換成Tester對象時,編譯器會把該函數(shù)當(dāng)作轉(zhuǎn)換構(gòu)造函數(shù)來調(diào)用。但是有時候,并不想把這種只有一個參數(shù)的構(gòu)造函數(shù)用于轉(zhuǎn)換目的,而僅僅希望用它來顯式地初始化對象,此時,就需要在構(gòu)造函數(shù)前加explicit。如果在聲明了Tester對象以后使用了下面的語句將導(dǎo)致一個錯誤:

ts=jd;//error

這個錯誤說明,雖然Tester類中有一個以Date型變量為參數(shù)的構(gòu)造函數(shù),編譯器卻不會把它看作是從Date到Tester的轉(zhuǎn)換構(gòu)造函數(shù),因?yàn)樗穆暶髦邪薳xplicit修飾符。

七、表達(dá)式內(nèi)部的轉(zhuǎn)換

在表達(dá)式內(nèi)部,如果發(fā)現(xiàn)某個類型和需要的不一致,就會發(fā)生錯誤。數(shù)字類型的轉(zhuǎn)換是很簡單,這里就不舉例了。下面的程序是把Date對象轉(zhuǎn)換成長整型值。

#includeiostream.h

classDate

{

intmo,da,yr;

public:

Date(intm,intd,inty)

{

mo=m;da=d;yr=y;

}

operatorlong();

};

Date::operatorlong()

{

staticintdys[]={31,28,31,30,31,30,31,31,30,31,30,31};

longdays=yr;

days*=365;

days+=(yr-1900)/4;//從1900年1月1日開始計(jì)算

for(inti=0;idays+=da;

returndays;

}

intmain()

{

Datetoday(12,24,2003);

constlongott=123;

longsum=ott+today;

cout<return0;

}

在表達(dá)式中,當(dāng)需要轉(zhuǎn)換的對象可以轉(zhuǎn)換成某個數(shù)字類型,或者表達(dá)式調(diào)用了作用于某個類的重載運(yùn)算符時,就會發(fā)生隱式轉(zhuǎn)換。運(yùn)算符重載以后再學(xué)習(xí)二級C++輔導(dǎo)筆記:私有數(shù)據(jù)成員和友元一、私有數(shù)據(jù)成員的使用

1.取值和賦值成員函數(shù)

面向?qū)ο蟮募s定就是保證所有數(shù)據(jù)成員的私有性。一般我們都是通過公有成員函數(shù)來作為公共接口來讀取私有數(shù)據(jù)成員的。某些時候,我們稱這樣的函數(shù)為取值和賦值函數(shù)。

取值函數(shù)的返回值和傳遞給賦值函數(shù)的參數(shù)不必一一匹配所有數(shù)據(jù)成員的類型。

#includeiostream.h

classDate

{

intmo,da,yr;

public:

Date(intm,intd,inty){mo=m;da=d;yr=y;}

intgetyear()const{returnyr;}

voidsetyear(inty){yr=y;}

};

intmain()

{

Datedt(4,1,89);

cout<dt.setyear(97);

cout<return0;

}

上面的例子很簡單,不分析了。要養(yǎng)成這樣的習(xí)慣,通過成員函數(shù)來訪問和改變類中的數(shù)據(jù)。這樣有利于軟件的設(shè)計(jì)和維護(hù)。比如,改變Date類內(nèi)部數(shù)據(jù)的形式,但仍然用修改過的getyear()和setyear()來提供訪問接口,那么使用該類就不必修改他們的代碼,僅需要重新編譯程序即可。

2.常量成員函數(shù)

注意上面的程序中g(shù)etyear()被聲明為常量型,這樣可以保證該成員函數(shù)不會修改調(diào)用他的對象。通過加上const修飾符,可以使訪問對象數(shù)據(jù)的成員函數(shù)僅僅完成不會引起數(shù)據(jù)變動的那些操作。

如果程序聲明某個Date對象為常量的話,那么該對象不得調(diào)用任何非常量型成員函數(shù),不論這些函數(shù)是否真的試圖修改對象的數(shù)據(jù)。只有把那些不會引起數(shù)據(jù)改變的函數(shù)都聲明為常量型,才可以讓常量對象來調(diào)用。

3.改進(jìn)的成員轉(zhuǎn)換函數(shù)

下面的程序改進(jìn)了從Date對象到CustomDate對象的成員轉(zhuǎn)換函數(shù),用取值和賦值函數(shù)取代了使用公有數(shù)據(jù)成員的做法。(以前的程序代碼在上一帖中)

#includeiostream.h

classCustomDate

{

intda,yr;

public:

CustomDate(){}

CustomDate(intd,inty){da=d;yr=y;}

voiddisplay()const{cout<intgetday()const{returnda;}

voidsetday(intd){da=d;}

};

classDate

{

intmo,da,yr;

public:

Date(intm,intd,inty){mo=m;da=d;yr=y;}

operatorCustomDate()const;

};

Date::operatorCustomDate()const

{

staticintdys[]={31,28,31,30,31,30,31,31,30,31,30,31};

CustomDatecd(0,yr);

intday=da;

for(inti=0;icd.setday(day);

returncd;

}

intmain()

{

Datedt(11,17,89);

CustomDatecd;

cd=dt;

cd.display();

return0;

}

注意上面的程序中Date::operatorCustomDate()聲明為常量型,因?yàn)檫@個函數(shù)沒有改變調(diào)用它對象的數(shù)據(jù),盡管它修改了一個臨時CustomDate對象并將其作為函數(shù)返回值。二、友元

前面已經(jīng)說過了,私有數(shù)據(jù)成員不能被類外的其他函數(shù)讀取,但是有時候類會允許一些特殊的函數(shù)直接讀寫其私有數(shù)據(jù)成員。

關(guān)鍵字friend可以讓特定的函數(shù)或者別的類的所有成員函數(shù)對私有數(shù)據(jù)成員進(jìn)行讀寫。這既可以維護(hù)數(shù)據(jù)的私有性,有可以保證讓特定的類或函數(shù)能夠直接訪問私有數(shù)據(jù)。

1.友元類

一個類可以聲明另一個類為其友元,這個友元的所有成員函數(shù)都可以讀寫它的私有數(shù)據(jù)。

#includeiostream.h

classDate;

classCustomDate

{

intda,yr;

public:

CustomDate(intd=0,inty=0){da=d;yr=y;}

voiddisplay()const{cout<friendDate;//這兒

};

classDate

{

intmo,da,yr;

public:

Date(intm,intd,inty){mo=m;da=d;yr=y;}

operatorCustomDate();

};

Date::operatorCustomDate()

{

staticintdys[]={31,28,31,30,31,30,31,31,30,31,30,31};

CustomDatecd(0,yr);

for(inti=0;icd.da+=da;

returncd;

}

intmain()

{

Datedt(11,17,89);

CustomDatecd(dt);

cd.display();

return0;

}

在上面的程序中,有這樣一句friendDate;該語句告訴編譯器,Date類的所有成員函數(shù)有權(quán)訪問CustomDate類的私有成員。因?yàn)镈ate類的轉(zhuǎn)換函數(shù)需要知道CustomDate類的每個數(shù)據(jù)成員,所以真?zhèn)€Date類都被聲明為CustomDate類的友元。

2.隱式構(gòu)造函數(shù)

上面程序?qū)ustomDate的構(gòu)造函數(shù)的調(diào)用私有顯示該類需要如下的一個轉(zhuǎn)換構(gòu)造函數(shù):

CustomDate(Date&dt);

但是唯一的一個構(gòu)造函數(shù)是:CustomDate(intd=0;inty=0);

這就出現(xiàn)了問題,編譯器要從Date對象構(gòu)造一個CustomDate對象,但是CustomDate類中并沒有定義這樣的轉(zhuǎn)換構(gòu)造函數(shù)。不過Date類中定義了一個成員轉(zhuǎn)換函數(shù),它可以把Date對象轉(zhuǎn)換成CustomDate對象。于是編譯器開始搜索CustomDate類,看其是否有一個構(gòu)造函數(shù),能從一個已存在的CustomDate的對象創(chuàng)建新的CustomDate對象。這種構(gòu)造函數(shù)叫拷貝構(gòu)造函數(shù)??截悩?gòu)造函數(shù)也只有一個參數(shù),該參數(shù)是它所屬的類的一個對象,由于CustomDate類中沒有拷貝構(gòu)造函數(shù),于是編譯器就會產(chǎn)生一個默認(rèn)的拷貝構(gòu)造函數(shù),該函數(shù)簡單地把已存在的對象的每個成員拷貝給新對象?,F(xiàn)在我們已經(jīng)知道,編譯器可以把Date對象轉(zhuǎn)換成CustomDate對象,也可以從已存在的CustomDate對象生成一個新的CustomDate對象。那么上面提出的問題,編譯器就是這樣做的:它首先調(diào)用轉(zhuǎn)換函數(shù),從Date對象創(chuàng)建一個隱藏的、臨時的、匿名的CustomDate對象,然后用該臨時對象作為參數(shù)調(diào)用默認(rèn)拷貝構(gòu)造函數(shù),這就生成了一個新的CustomDate對象。

3.預(yù)引用

上面的例子中還有這樣一句classDate;

這個語句叫做預(yù)引用。它告訴編譯器,類Date將在后面定義。編譯器必須知道這個信號,因?yàn)镃ustomDate類中引用了Date類,而Date里也引用了CustomDate類,必須首先聲明其中之一。

使用了預(yù)引用后,就可以聲明未定義的類的友元、指針和引用。但是不可以使用那些需要知道預(yù)引用的類的定義細(xì)節(jié)的語句,如聲明該類的一個實(shí)例或者任何對該類成員的引用。

4.顯式友元預(yù)引用

也可以不使用預(yù)引用,這只要在聲明友元的時候加上關(guān)鍵自class就行了。

#includeiostream.h

classCustomDate

{

intda,yr;

public:

CustomDate(intd=0,inty=0){da=d;yr=y;}

voiddisplay()const{cout<friendclassDate;//這兒,去掉前面的預(yù)引用

};

classDate

{

......

};

Date::operatorCustomDate()

{

......

}

intmain()

{

......

}5.友元函數(shù)

通常,除非真的需要,否則并不需要把整個類都設(shè)為另一個類的友元,只需挑出需要訪問當(dāng)前類私有數(shù)據(jù)成員的成員函數(shù),將它們設(shè)置為該類的友元即可。這樣的函數(shù)稱為友元函數(shù)。

下面的程序限制了CustomDate類數(shù)據(jù)成員的訪問,Date類中只有需要這些數(shù)據(jù)的成員函數(shù)才有權(quán)讀寫它們。

#includeiostream.h

classCustomDate;

classDate

{

intmo,da,yr;

public:

Date(constCustomDate&);

voiddisplay()const{cout<};

classCustomDate

{

intda,yr;

public:

CustomDate(intd=0,inty=0){da=d;yr=y;}

friendDate::Date(constCustomDate&);

};

Date::Date(constCustomDate&cd)

{

staticintdys[]={31,28,31,30,31,30,31,31,30,31,30,31};

yr=cd.yr;

da=cd.da;

for(mo=0;mo<11;mo++)

if(da>dys[mo])da-=dys[mo];

elsebreak;

mo++;

}

intmain()

{

Datedt(CustomDate(123,89));

dt.display();

return0;

}

6.匿名對象

上面main()函數(shù)中Date對象調(diào)用CustomDate類的構(gòu)造函數(shù)創(chuàng)建了一個匿名CustomDate對象,然后用該對象創(chuàng)建了一個Date對象。這種用法在C++中是經(jīng)常出現(xiàn)的。

7.非類成員的友元函數(shù)

有時候友元函數(shù)未必是某個類的成員。這樣的函數(shù)擁有類對象私有數(shù)據(jù)成員的讀寫權(quán),但它并不是任何類的成員函數(shù)。這個特性在重載運(yùn)算符時特別有用。

非類成員的友元函數(shù)通常被用來做為類之間的紐帶。一個函數(shù)如果被兩個類同時聲明為友元,它就可以訪問這兩個類的私有成員。下面的程序說明了一個可以訪問兩個類私有數(shù)據(jù)成員的友元函數(shù)是如何將在兩個類之間架起橋梁的。

#includeiostream.h

classTime;

classDate

{

intmo,da,yr;

public:

Date(intm,intd,inty){mo=m;da=d;yr=y;}

friendvoiddisplay(constDate&,constTime&);

};

classTime

{

inthr,min,sec;

public:

Time(inth,intm,ints){hr=h;min=m;sec=s;}

friendvoiddisplay(constDate&,constTime&);

};

voiddisplay(constDate&dt,constTime&tm)

{

cout<<dt.mo<<'/'<<dt.da<<'/'<<dt.yr;

cout<<'';

cout<<tm.hr<<':'<<tm.min<<':'<<tm.sec;

}

intmain()

{

Datedt(2,16,97);

Timetm(10,55,0);

display(dt,tm);

return0;

}二級C++輔導(dǎo)筆記:析構(gòu)函數(shù)和this指針一、析構(gòu)函數(shù)

前面的一些例子都沒有說明析構(gòu)函數(shù),這是因?yàn)樗玫降念愒诮Y(jié)束時不需要做特別的清理工作。下面的程序給出了一新的Date類,其中包括一個字符串指針,用來表示月份。

#includeiostream.h

#includestring.h

classDate

{

intmo,da,yr;

char*month;

public:

Date(intm=0,intd=0,inty=0);

~Date();

voiddisplay()const;

};

Date::Date(intm,intd,inty)

{

staticchar*mos[]=

{

January,February,March,April,May,June,

July,August,September,October,November,December

};

mo=m;da=d;yr=y;

if(m!=0)

{

month=newchar[strlen(mos[m-1])+1];

strcpy(month,mos[m-1]);

}

elsemonth=0;

}

Date::~Date()

{

delete[]month;

}

voidDate::display()const

{

if(month!=0)cout<}

intmain()

{

Datebirthday(8,11,1979);

birthday.display();

return0;

}

在Date對象的構(gòu)造函數(shù)中,首先用new運(yùn)算符為字符串month動態(tài)分配了內(nèi)存,然后從內(nèi)部數(shù)組中把月份的名字拷貝給字符串指針month。

析構(gòu)函數(shù)在刪除month指針時,可能會出現(xiàn)一些問題。當(dāng)然從這個程序本身來看,沒什么麻煩;但是從設(shè)計(jì)一個類的角度來看,當(dāng)Date類用于賦值時,就會出現(xiàn)問題。假設(shè)上面的main()修改為“

intmain()

{

Datebirthday(8,11,1979);

Datetoday;

today=birthday;

birthday.display();

return0;

}

這會生成一個名為today的空的Date型變量,并且把birthday值賦給它。如果不特別通知編譯器,它會簡單的認(rèn)為類的賦值就是成員對成員的拷貝。在上面的程序中,變量birthday有一個字符型指針month,并且在構(gòu)造函數(shù)里用new運(yùn)算符初始化過了。當(dāng)birthday離開其作用域時,析構(gòu)函數(shù)會調(diào)用delete運(yùn)算符來釋放內(nèi)存。但同時,當(dāng)today離開它的作用域時,析構(gòu)函數(shù)同樣會對它進(jìn)行釋放操作,而today里的month指針是birthday里的month指針的一個拷貝。析構(gòu)函數(shù)對同一指針進(jìn)行了兩次刪除操作,這會帶來不可預(yù)知的后果。

如果假設(shè)today是一個外部變量,而birthday是一個自變量。當(dāng)birthday離開其作用域時,就已經(jīng)把對象today里的month指針刪除了。顯然這也是不正確的。

再假設(shè)有兩個初始化的Date變量,把其中一個的值賦值給另一個:

Datebirthday(8,11,1979);

Datetoday(12,29,2003);

today=birthday;

問題就更復(fù)雜了,當(dāng)這兩個變量離開作用域時,birthday中的month的值已經(jīng)通過賦值傳遞給了today。而today中構(gòu)造函數(shù)用new運(yùn)算符給month的值卻因?yàn)橘x值被覆蓋了。這樣,birthday中的month被刪除了兩次,而today中month卻沒有被刪除掉。

二、重載賦值運(yùn)算符

為了解決上面的問題,我們應(yīng)該寫一個特殊的賦值運(yùn)算符函數(shù)來處理這類問題。當(dāng)需要為同一個類的兩個對象相互賦值時,就可以重載運(yùn)算符函數(shù)。這個方法可以解決類的賦值和指針的釋放。

下面的程序中,類中的賦值函數(shù)用new運(yùn)算符從堆中分配了一個不同的指針,該指針獲取賦值對象中相應(yīng)的值,然后拷貝給接受賦值的對象。

在類中重載賦值運(yùn)算符的格式如下:

voidoperator=(constDate&)

后面我們回加以改進(jìn)。目前,重載的運(yùn)算符函數(shù)的返回類型為void。它是類總的成員函數(shù),在本程序紅,是Date類的成員函數(shù)。它的函數(shù)名始終是operator=,參數(shù)也始終是同一個類的對象的引用。參數(shù)表示的是源對象,即賦值數(shù)據(jù)的提供者。重載函數(shù)的運(yùn)算符作為目標(biāo)對象的成員函數(shù)來使用。

#includeiostream.h

#includestring.h

classDate

{

intmo,da,yr;

char*month;

public:

Date(intm=0,intd=0,inty=0);

~Date();

voidoperator=(constDate&);

voiddisplay()const;

};

Date::Date(intm,intd,inty)

{

staticchar*mos[]=

{

January,February,March,April,May,June,

July,August,September,October,November,December

};

mo=m;da=d;yr=y;

if(m!=0)

{

month=newchar[strlen(mos[m-1])+1];

strcpy(month,mos[m-1]);

}

elsemonth=0;

}

Date::~Date()

{

delete[]month;

}

voidDate::display()const

{

if(month!=0)cout<charname[25];

cin>>name;

if(strncmp(name,end,3)==0)break;

ListEntry*list=newListEntry(name);

if(prev!=0)prev->AddEntry(*list);

prev=list;

}

while(prev!=0)

{

prev->display();

ListEntry*hold=prev;

prev=prev->PrevEntry();

deletehold;

}

return0;

}

程序運(yùn)行時,會提示輸入一串姓名,當(dāng)輸入完畢后,鍵入end,然后程序會逆序顯示剛才輸入的所有姓名。

程序中ListEntry類含有一個字符串和一個指向前一個表項(xiàng)的指針。構(gòu)造函數(shù)從對中獲取內(nèi)存分配給字符串,并把字符串的內(nèi)容拷貝到內(nèi)存,然后置鏈接指針為NULL。析構(gòu)函數(shù)將釋放字符串所占用的內(nèi)存。

成員函數(shù)PrevEntry()返回指向鏈表前一個表項(xiàng)的指針。另一個成員函數(shù)顯示當(dāng)前的表項(xiàng)內(nèi)容。

成員函數(shù)AddEntry(),它把this指針拷貝給參數(shù)的preventry指針,即把當(dāng)前表項(xiàng)的地址賦值給下一個表項(xiàng)的鏈接指針,從而構(gòu)造了一個鏈表。它并沒有改變調(diào)用它的listEntry對象的內(nèi)容,只是把該對象的地址賦給函數(shù)的參數(shù)所引用的那個ListEntry對象的preventry指針,盡管該函數(shù)不會修改對象的數(shù)據(jù),但它并不是常量型。這是因?yàn)椋截悓ο蟮牡刂穞his指針的內(nèi)容給一個非長常量對象,而編譯器回認(rèn)為這個非常量對象就有可能通過拷貝得到的地址去修改當(dāng)前對象的數(shù)據(jù),因此AddEntry()函數(shù)在聲明時不需要用const.二級C++輔導(dǎo)筆記:類對象數(shù)組和靜態(tài)成員一、類對象數(shù)組

類的對象和C++其他數(shù)據(jù)類型一樣,也可以為其建立數(shù)組,數(shù)組的表示方法和結(jié)構(gòu)一樣。

#includeiostream.h

classDate

{

intmo,da,yr;

public:

Date(intm=0,intd=0,inty=0){mo=m;da=d;yr=y;}

voiddisplay()const{cout<};

intmain()

{

Datedates[2];

Datetoday(12,31,2003);

dates[0]=today;

dates[0].display();

dates[1].display();

return0;

}

1.類對象數(shù)組和默認(rèn)構(gòu)造函數(shù)

在前面已經(jīng)說過,不帶參數(shù)或者所有參數(shù)都有默認(rèn)值的構(gòu)造函數(shù)叫做默認(rèn)構(gòu)造函數(shù)。如果類中沒有構(gòu)造函數(shù),編譯器會自動提供一個什么都不做的公共默認(rèn)構(gòu)造函數(shù)。如果類當(dāng)中至少有一個構(gòu)造函數(shù),編譯器就不會提供默認(rèn)構(gòu)造函數(shù)。

如果類當(dāng)中不含默認(rèn)構(gòu)造函數(shù),則無法實(shí)例化其對象數(shù)組。因?yàn)閷?shí)例花類對象數(shù)組的格式不允許用初始化值來匹配某個構(gòu)造函數(shù)的參數(shù)表。

上面的程序中,main()函數(shù)聲明了一個長度為2的Date對象數(shù)組,還有一個包含初始化值的單個Date對象。接著把這個初始化的Date對象賦值給數(shù)組中第一個對象,然后顯示兩個數(shù)組元素中包含的日期。從輸出中可以看到,第一個日期是有效日期,而第二個顯示的都是0。

當(dāng)聲明了某個類的對象數(shù)組時,編譯器會為每個元素都調(diào)用默認(rèn)構(gòu)造函數(shù)。

下面的程序去掉了構(gòu)造函數(shù)的默認(rèn)參數(shù)值,并且增加了一個默認(rèn)構(gòu)造函數(shù)。

#include

classDate

{

intmo,da,yr;

public:

Date();

Date(intm,intd,inty){mo=m;da=d;yr=y;}

voiddisplay()const{cout<};

Date::Date()

{

cout<mo=0;da=0;yr=0;

}

intmain()

{

Datedates[2];

Datetoday(12,31,2003);

dates[0]=today;

dates[0].display();

dates[1].display();

return0;

}

運(yùn)行程序,輸出為:

Dateconstructorrunning

Dateconstructorrunning

12/31/2003

0/0/0

從輸出中可以看出,Date()這個默認(rèn)構(gòu)造函數(shù)被調(diào)用了兩次。

2.類對象數(shù)組和析構(gòu)函數(shù)

當(dāng)類對象離開作用域時,編譯器會為每個對象數(shù)組元素調(diào)用析構(gòu)函數(shù)。

#includeiostream.h

classDate

{

intmo,da,yr;

public:

Date(intm=0,intd=0,inty=0){mo=m;da=d;yr=y;}

~Date(){cout<voiddisplay()const{cout<};

intmain()

{

Datedates[2];

Datetoday(12,31,2003);

dates[0]=today;

dates[0].display();

dates[1].display();

return0;

}

運(yùn)行程序,輸出為:

12/31/2003

0/0/0

Datedestructorrunning

Datedestructorrunning

Datedestructorrunning

表明析構(gòu)函數(shù)被調(diào)用了三次,也就是dates[0],dates[1],today這三個對象離開作用域時調(diào)用的。二、靜態(tài)成員

可以把類的成員聲明為靜態(tài)的。靜態(tài)成員只能存在唯一的實(shí)例。所有的成員函數(shù)都可以訪問這個靜態(tài)成員。即使沒有聲明類的任何實(shí)例,靜態(tài)成員也已經(jīng)是存在的。不過類當(dāng)中聲明靜態(tài)成員時并不能自動定義這個變量,必須在類定義之外來定義該成員。

1.靜態(tài)數(shù)據(jù)成員

靜態(tài)數(shù)據(jù)成員相當(dāng)于一個全局變量,類的所有實(shí)例都可以使用它。成員函數(shù)能訪問并且修改這個值。如果這個靜態(tài)成員是公有的,那么類的作用域之內(nèi)的所有代碼(不論是在類的內(nèi)部還是外部)都可以訪問這個成員。下面的程序通過靜態(tài)數(shù)據(jù)成員來記錄鏈表首項(xiàng)和末項(xiàng)的地址。

#includeiostream.h

#includestring.h

classListEntry

{

public:

staticListEntry*firstentry;

private:

staticListEntry*lastentry;

char*listvalue;

ListEntry*nextentry;

public:

ListEntry(char*);

~ListEntry(){delete[]listvalue;}

ListEntry*NextEntry()const{returnnextentry;};

voiddisplay()const{cout<};

ListEntry*ListEntry::firstentry;

ListEntry*ListEntry::lastentry;

ListEntry::ListEntry(char*s)

{

if(firstentry==0)firstentry=this;

if(lastentry!=0)lastentry->nextentry=this;

lastentry=this;

listvalue=newchar[strlen(s)+1];

strcpy(listvalue,s);

nextentry=0;

}

intmain()

{

while(1)

{

cout<<\nEnteraname('end'whendone):;

charname[25];

cin>>name;

if(strncmp(name,end,3)==0)break;

newListEntry(name);

}

ListEntry*next=ListEntry::firstentry;

while(next!=0)

{

next->display(

溫馨提示

  • 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

提交評論