在生活中,我們通常用“類(lèi)”這個(gè)字來(lái)形容具有共同特點(diǎn)的一類(lèi)事物,如:人類(lèi)、鼠類(lèi)、犬類(lèi),也許在具體的行為或特征方面上,同類(lèi)不同個(gè)體會(huì)具有差異化,但是在宏觀的角度而言也具有一定的相似性;
創(chuàng)新互聯(lián)專(zhuān)注于企業(yè)營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、網(wǎng)站重做改版、合川網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5場(chǎng)景定制、商城網(wǎng)站制作、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性?xún)r(jià)比高,為合川等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。例如:人類(lèi)的個(gè)體可能會(huì)有性格上的差異,體重上的差異,但是都需要呼吸以維持聲明,因此我們用人類(lèi)來(lái)比擬c++中“類(lèi)”這一概念的話(huà),那么具體的某一個(gè)人就是這一個(gè)“類(lèi)”中的一個(gè)對(duì)象;
(2)創(chuàng)建一個(gè)簡(jiǎn)單的類(lèi):類(lèi)和我們所熟知的數(shù)據(jù)類(lèi)型并無(wú)差異,只是相對(duì)而言,我們可以更為自由靈活的去創(chuàng)建一個(gè)對(duì)象或者變量,而不再受數(shù)據(jù)類(lèi)型本身的限制,因?yàn)閷?duì)于一個(gè)復(fù)雜的個(gè)體而言,其所要儲(chǔ)存的數(shù)據(jù)不可能只是單純的int類(lèi)型、float類(lèi)型或者是char類(lèi)型等等,有可能是他們之中幾個(gè)的結(jié)合,或者說(shuō)我們所要儲(chǔ)存的東西甚至無(wú)法用單純的用數(shù)據(jù)來(lái)描述,也就是“行為”,換句話(huà)就是“函數(shù)”;
那么創(chuàng)建一個(gè)類(lèi)之前我們要先知道聲明“類(lèi)”所用的關(guān)鍵字:“class”
類(lèi)的語(yǔ)法:
class類(lèi)名{
??訪(fǎng)問(wèn)修飾符:
????成員變量、函數(shù)等;
};
#includeusingnamespacestd;
classPeople{
??stringname;
??intage;
??floatweight;
??doubleheight;
};
如上述代碼所示,我們已經(jīng)創(chuàng)建了一個(gè)類(lèi),類(lèi)名為“People”,其中的變量包括:string類(lèi)型的name,int類(lèi)型的age,float類(lèi)型的weight,double類(lèi)型的身高,這些變量我們稱(chēng)之為成員變量,也稱(chēng)為類(lèi)的屬性;
(3)訪(fǎng)問(wèn)權(quán)限修飾符但是我們并不想讓任何人都可以隨意的訪(fǎng)問(wèn)這些屬性,因此在類(lèi)中我們可以利用三種訪(fǎng)問(wèn)修飾符對(duì)類(lèi)中不同的變量進(jìn)行修飾分別為:
①“public”:公共的,任何位置都有權(quán)限訪(fǎng)問(wèn);
②“private”:私有的,只有當(dāng)前類(lèi)內(nèi)有權(quán)限訪(fǎng)問(wèn);
③“protected”:受保護(hù)的,類(lèi)內(nèi)和子類(lèi)有權(quán)限訪(fǎng)問(wèn);
注:在類(lèi)的定義中,未被訪(fǎng)問(wèn)修飾符所修飾的成員變量或成員函數(shù)默認(rèn)為private;
由于同一類(lèi)別的不同對(duì)象會(huì)具差異化,也就是具有不同的屬性,因此我們通常不會(huì)直接在類(lèi)中去給屬性賦值,而是在創(chuàng)建對(duì)象時(shí)去初始化其中的屬性,那么我們來(lái)創(chuàng)建一個(gè)屬于“People”類(lèi)的對(duì)象:
#includeusingnamespacestd;
classPeople{
??private:
????intage;
floatweight;
??public:
??stringname;
??doubleheight;
};
intmain(){
??PeopleXiao_Ming;
}
此時(shí),我們已經(jīng)在主函數(shù)中,創(chuàng)建了一個(gè)屬于“People”類(lèi)的對(duì)象:“Xiao_Ming”,由于Xiao_Ming屬于People類(lèi),因此,其具有People類(lèi)中的所有屬性和行為(什么是行為我們一會(huì)再說(shuō));
2、類(lèi)的初始化 (1)類(lèi)外直接進(jìn)行賦值初始化首先聲明(1)~(4)的本質(zhì)都是賦值,并不是真正意義上的初始化,具體原因在(5)中說(shuō)明;
現(xiàn)在的Xiao_Ming是一個(gè)剛創(chuàng)建好的對(duì)象,我們需要對(duì)他的屬性進(jìn)行初始化(賦值),如果想要在類(lèi)外調(diào)用類(lèi)成員的話(huà)我們使用“.”來(lái)實(shí)現(xiàn),具體語(yǔ)法:“對(duì)象名.成員變量”,而由于訪(fǎng)問(wèn)權(quán)限是“public”的成員變量只有name和height,因此我們?cè)陬?lèi)外只能初始化public類(lèi)型的成員變量:
#includeusingnamespacestd;
classPeople{
private:
intage;
floatweight;
public:
stringname;
doubleheight;
};
intmain(){
PeopleXiao_Ming;
??//類(lèi)外進(jìn)行賦值初始化
??Xiao_Ming.name="Xiao_Ming";
??Xiao_Ming.height=175.9;
}
但此時(shí)出現(xiàn)了一個(gè)問(wèn)題,被“private”修飾的變量無(wú)法在類(lèi)外進(jìn)行操作,但是我們創(chuàng)建對(duì)象的時(shí)候一定是在類(lèi)外創(chuàng)建的,這就形成了矛盾,這就需要我們使用類(lèi)的行為來(lái)修改屬性;
(2)利用類(lèi)的行為修改對(duì)象屬性類(lèi)內(nèi)的函數(shù)就可以看作是類(lèi)的行為,由于被private修飾的變量只能在類(lèi)內(nèi)進(jìn)行訪(fǎng)問(wèn),然而我們無(wú)法在類(lèi)內(nèi)直接進(jìn)行賦值操作,因此,我們可以在類(lèi)中定義一個(gè)可以接收參數(shù)的函數(shù)用來(lái)修改類(lèi)內(nèi)成員變量的值,這就實(shí)現(xiàn)了用類(lèi)的行為改變對(duì)象的屬性,從而可以靈活的初始化我們所創(chuàng)建的不同對(duì)象;
#includeusingnamespacestd;
classPeople{
private:
intage;
floatweight;
public:
stringname;
doubleheight;
//在主函數(shù)中接收初始化的參數(shù)用于給age和weight賦值
voidpeople_initial(intn,floatm){
age=n;
weight=m;
}
//可以打印輸出age和weight的值
voidpeople_display(){
cout<
并且,我們可以創(chuàng)建多個(gè)對(duì)象,再依次進(jìn)行賦值,并打印輸出:
#includeusingnamespacestd;
classPeople{
private:
intage;
floatweight;
public:
stringname;
doubleheight;
//在主函數(shù)中接收初始化的參數(shù)用于給age和weight賦值
voidpeople_initial(intn,floatm){
age=n;
weight=m;
}
//可以打印輸出age和weight的值
voidpeople_display(){
cout<
但是如果我們的對(duì)象有很多,我們不可能在主函數(shù)中依次進(jìn)行賦值操作,去完成所有對(duì)象的初始化,于是c++的類(lèi)為我們提供了一種更為便捷的初始化方式——構(gòu)造函數(shù);
(3)利用”構(gòu)造函數(shù)“初始化變量首先我們要清楚什么是構(gòu)造函數(shù),每當(dāng)我們創(chuàng)建一個(gè)類(lèi)的對(duì)象時(shí),系統(tǒng)會(huì)默認(rèn)調(diào)用構(gòu)造函數(shù)對(duì)我們所創(chuàng)建的對(duì)象進(jìn)行賦值初始化操作,如果我們沒(méi)有在類(lèi)中定義構(gòu)造函數(shù),那么系統(tǒng)則會(huì)調(diào)用默認(rèn)的構(gòu)造函數(shù)進(jìn)行初始化,且構(gòu)造函數(shù)沒(méi)有返還值,故也不存在返還值類(lèi)型一說(shuō);
構(gòu)造函數(shù)的語(yǔ)法如下:
類(lèi)名(參數(shù)){
初始化操作程序;
}
調(diào)用構(gòu)造函數(shù)的語(yǔ)法如下:
類(lèi)名變量名(參數(shù));
那么,我們利用這一方法來(lái)重新創(chuàng)建對(duì)象:
#includeusingnamespacestd;
classPeople{
public:
//構(gòu)造函數(shù)
People(intn,intm,stringx,inty){
??????//將傳入的參數(shù)依次賦值給成員變量
age=n;
weight=m;
name=x;
height=y;
}
//成員變量
stringname;
intheight;
voidpeople_display(){
cout<<"name:"<對(duì)于該程序而言,我們自己定義了類(lèi)中的構(gòu)造函數(shù),那么系統(tǒng)將不會(huì)調(diào)用默認(rèn)構(gòu)造函數(shù),系統(tǒng)的默認(rèn)構(gòu)造函數(shù)是無(wú)參數(shù)構(gòu)造類(lèi)型的函數(shù),也就是說(shuō)其只負(fù)責(zé)在棧區(qū)開(kāi)辟當(dāng)前對(duì)象所需要的內(nèi)存空間,不會(huì)進(jìn)行賦值初始化等操作,而我們通過(guò)自己定義構(gòu)造函數(shù),從而完善了他的功能性
但是,假如現(xiàn)在我們要定義兩個(gè)對(duì)象時(shí),我們希望其中一個(gè)進(jìn)行初始化,一個(gè)不進(jìn)行初始化,那么我們按照之前的寫(xiě)法,如下所示:
intmain(){
??//Xiao_Ming進(jìn)行初始化
PeopleXiao_Ming(18,60,"Xiao_Ming",180);
??//Xiao_Li不進(jìn)行初始化
??PeopleXiao_Li;
}
此時(shí)編譯器會(huì)對(duì)代碼的第5行進(jìn)行報(bào)錯(cuò)提醒:類(lèi)People不存在默認(rèn)構(gòu)造函數(shù),也就是所,系統(tǒng)找不到與之匹配的構(gòu)造函數(shù)類(lèi)型,因此想要完成目標(biāo),我們就需要利用c++中函數(shù)重載的特性;
(4)函數(shù)重載什么是重載函數(shù),在c++中我們可以定義多個(gè)名字相同的函數(shù),但是其傳輸?shù)膮?shù)的個(gè)數(shù),類(lèi)型,順序不同,此時(shí)編譯器會(huì)跟據(jù)調(diào)用該函數(shù)時(shí),其所傳入的參數(shù)的類(lèi)型來(lái)判斷具體調(diào)用哪個(gè)函數(shù),函數(shù)重載具有以下幾個(gè)特點(diǎn):
c++允許在一個(gè)作用域中(一個(gè){}中)的某個(gè)函數(shù)有多種定義;
在同一個(gè)作用域內(nèi)可以聲明幾個(gè)功能類(lèi)似的同名函數(shù),但是這些同名函數(shù)的形參必須不同(順序、類(lèi)別、個(gè)數(shù)、const修飾)不可以?xún)H僅通過(guò)返還值類(lèi)型的不同來(lái)重載函數(shù);
調(diào)用重載函數(shù)時(shí),編譯器通過(guò)把你所使用的參數(shù)類(lèi)型與定義的參數(shù)進(jìn)行比較,決定最合適的定義,該過(guò)程稱(chēng)作”重載決策“;
那么我們可以利用該特性,在類(lèi)中定義多個(gè)構(gòu)造函數(shù),從而適應(yīng)多種對(duì)象初始化的情況:
#includeusingnamespacestd;
classPeople{
public:
//構(gòu)造函數(shù)1(有參數(shù))
People(intn,intm,stringx,inty){
age=n;
weight=m;
name=x;
height=y;
//構(gòu)造函數(shù)2(無(wú)參數(shù))
}People(){
age=0;
weight=0;
name="尚未填寫(xiě)";
height=0;
}
//成員變量
stringname;
intheight;
voidpeople_display(){
cout<<"name:"<在這段代碼中,我們用兩種的初始化方式,創(chuàng)建了對(duì)象Xiao_Ming和Xiao_Li;
注意:
這里我們?cè)谡{(diào)用構(gòu)造函數(shù)2也就是無(wú)參構(gòu)造的時(shí)候,我們的寫(xiě)法是
PeopleXiao_Li;
而不是:
PeopleXiao_Li();
因?yàn)椋覀內(nèi)绻麑?xiě)作第二種形式的話(huà),編譯器會(huì)認(rèn)為我們是在做函數(shù)聲明,聲明了一個(gè)返還值類(lèi)型為People類(lèi)的函數(shù),而不會(huì)將其認(rèn)為是在調(diào)用無(wú)參的構(gòu)造函數(shù)
(5)初始化參數(shù)列表首先,我們要明白初始化和賦值的區(qū)別,初始化是在變量聲明(分配好空間)的同時(shí)就為該變量所處的內(nèi)區(qū)域的內(nèi)存空間給予一個(gè)確定的值,而賦值則是清除空間的舊值并用新的值做拷貝替換,換而言之,賦值操作是初始化的一部分,如下代碼所示:
intmain(){
??//對(duì)a進(jìn)行初始化
??inta=1;
??//對(duì)b進(jìn)行賦值
??intb;
??b=3
}
就實(shí)際意義,二者沒(méi)有任何的區(qū)別,但是從代碼運(yùn)行的角度,賦值操作的本質(zhì)是拷貝,也就是將已有的值從常量區(qū)復(fù)制拷貝到新的空間中去(具體可參考此文章:內(nèi)存管理),因此,賦值相較于直接進(jìn)行初始化而言會(huì)多進(jìn)行一步復(fù)制拷貝的操作,故對(duì)于一些比較統(tǒng)一的成員變量我們可以考慮統(tǒng)一用初始化參數(shù)列表進(jìn)行初始化,這樣效率更高;
在使用初始化參數(shù)列表時(shí)注意:
只能在構(gòu)造函數(shù)中使用初始化參數(shù)列表,可以給所有成員初始化;
成員的初始化順序與類(lèi)中的聲明順序一致,而與參數(shù)列表中的順序無(wú)關(guān);
const類(lèi)型的變量和引用類(lèi)型的變量必須在初始化參數(shù)列表中完成;
其中最后一條的原因:因?yàn)橐坏┪覀儎?chuàng)建了一個(gè)對(duì)象其內(nèi)部的值如果未初始化就會(huì)被不確定的值所覆蓋,構(gòu)造函數(shù)中只能進(jìn)行賦值操作,而無(wú)論是const類(lèi)型的變量還是引用類(lèi)型的變量都是不能進(jìn)行賦值的,所以只能在初始化參數(shù)列表中進(jìn)行初始化操作;
初始化參數(shù)列表的語(yǔ)法:
//構(gòu)造函數(shù)
類(lèi)名():成員變量1(給變量1初始化的值),成員變量2(給變量2初始化的值){
??構(gòu)造函數(shù)內(nèi)程序段;??
}
那么假設(shè),我們現(xiàn)在要寫(xiě)一段程序,用來(lái)記錄一個(gè)人信譽(yù)積分系統(tǒng),起初每個(gè)人都是100分,每犯一次錯(cuò)誤,就會(huì)減少1分:
#includeusingnamespacestd;
classpeople{
private:
stringname;
intscore;
public:
people(stringinput):score(100){
name=input;
}
voidmake_mistake(){
score--;
}
voidscore_display(){
cout<
對(duì)應(yīng)這里的實(shí)際情況,因?yàn)槊總€(gè)人姓名都是不同的,因此我們將其以形參的形式傳入到構(gòu)造函數(shù)中,并傳參到name中進(jìn)行賦值,而由于每個(gè)人的初始分?jǐn)?shù)都是100,故放在初始化參數(shù)列表中進(jìn)行直接初始化,從而高效的實(shí)現(xiàn)了這一程序;
3、析構(gòu)函數(shù)和構(gòu)造函數(shù)的功能相對(duì)應(yīng),構(gòu)造函數(shù)用于初始化類(lèi)的對(duì)象,而析構(gòu)函數(shù)則是用于清理釋放掉生命周期已經(jīng)結(jié)束的對(duì)象(對(duì)象聲明處所在的{}內(nèi)為其整個(gè)生命周期);
與構(gòu)造函數(shù)相同的是,如果我們未在類(lèi)中定義析構(gòu)函數(shù),那么在某一個(gè)對(duì)象的生命周結(jié)束時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用默認(rèn)的析構(gòu)函數(shù)釋放其所占用的內(nèi)存空間,但是系統(tǒng)只能自動(dòng)清理?xiàng)^(qū)空間,如果我們?cè)跇?gòu)造函數(shù)中對(duì)我們的對(duì)象進(jìn)行初始化的時(shí)候使用new或malloc這類(lèi)函數(shù)向堆區(qū)申請(qǐng)了額外空間的話(huà),需要手動(dòng)用delet或free來(lái)釋放這部分的空間,因此,需要自己在類(lèi)中定義析構(gòu)函數(shù),從而完成其功能;
對(duì)于析構(gòu)函數(shù),其語(yǔ)法為:
~類(lèi)名(){
??析構(gòu)函數(shù)內(nèi)程序段;
}
那么我們來(lái)看以下的程序:
#include#includeusingnamespacestd;
classpeople{
public:
people(constchar*xh,constchar*dh){
std_id=newchar[32];
strcpy(std_id,xh);
tel=newchar[32];
strcpy(tel,dh);
}
~people(){
delete[]std_id;
delete[]tel;
}
voidinf_display(){
cout<<"std_id:"<
4、靜態(tài)成員
(1)靜態(tài)成員變量我們用關(guān)鍵字“static”修飾一個(gè)類(lèi)中的成員變量時(shí),我們稱(chēng)該變量是靜態(tài)成員變量,通過(guò)普通的靜態(tài)變量的特點(diǎn)我們可以知道,靜態(tài)變量?jī)?chǔ)存在全局區(qū),生命周期是從程序開(kāi)始到程序結(jié)束,也就是說(shuō)對(duì)于同一個(gè)類(lèi)的多個(gè)對(duì)象而言,其靜態(tài)成員是公用的,并不會(huì)隨對(duì)象的創(chuàng)建而分配內(nèi)存,也不會(huì)隨某一個(gè)對(duì)象釋放時(shí)而釋放內(nèi)存;
靜態(tài)變量初始化的時(shí)候可以賦初值,也可以不賦初值,其默認(rèn)為0,但是如果對(duì)其賦值應(yīng)該在類(lèi)外進(jìn)行初始化!
那么利用這一特點(diǎn),我們可以利用靜態(tài)成員變量來(lái)記錄我們所創(chuàng)建的對(duì)象的個(gè)數(shù),如下代碼所示:
#includeusingnamespacestd;
classpeople{
public:
staticintnum_people;
people(){
num_people++;
}
people(stringname,intage){
num_people++;
}
????~people(){
??????num_people--;
????{
};
//靜態(tài)成員變量初始化
intpeople::num_people=0;
intmain(){
peopleXiao_Ming();
peopleXiao_Li("Xiao_Li",18);
cout<
也就是每當(dāng)我們的程序調(diào)用了構(gòu)造函數(shù)時(shí),說(shuō)明該增加了一個(gè)該類(lèi)的對(duì)象,就會(huì)對(duì)num_people加1,而每當(dāng)程序調(diào)用了析構(gòu)函數(shù)時(shí),說(shuō)明有一個(gè)對(duì)象被釋放了,從而num_people減1;
而且這段程序中值得我們注意的是:我們?cè)谥骱瘮?shù)的結(jié)尾,輸出當(dāng)前對(duì)象個(gè)數(shù)的時(shí)候,我們使用的是“::”而不是“.”,這就說(shuō)明靜態(tài)成員變量不屬于某個(gè)對(duì)象,而是屬于整個(gè)類(lèi)的;
因此,對(duì)于靜態(tài)成員變量需要注意的是:
靜態(tài)成員變量屬于整個(gè)類(lèi)所有,所有對(duì)象共享其所屬類(lèi)的靜態(tài)成員變量;
靜態(tài)成員變量的初始化應(yīng)該在類(lèi)外進(jìn)行;
可以通過(guò)類(lèi)名直接訪(fǎng)問(wèn)公有(public)靜態(tài)成員變量;
可以通過(guò)對(duì)象名直接訪(fǎng)問(wèn)公有(public)靜態(tài)成員變量;
靜態(tài)成員變量在程序內(nèi)部位于全局區(qū)(靜態(tài)區(qū));
靜態(tài)成員變量的生命周期不依賴(lài)于任何的對(duì)象,與程序的生命周期一致;
(2)靜態(tài)成員函數(shù)(this指針)用staitic來(lái)修飾類(lèi)中的成員函數(shù),該函數(shù)便稱(chēng)為靜態(tài)成員函數(shù),與靜態(tài)成員變量一致,靜態(tài)成員函數(shù)也是歸類(lèi)所屬,而非是某一個(gè)對(duì)象;
對(duì)靜態(tài)成員函數(shù)最重要的特點(diǎn)是其只能訪(fǎng)問(wèn)靜態(tài)成員變量或其他的靜態(tài)成員函數(shù),原因在于其內(nèi)部沒(méi)有“this”指針;
“this”指針也被稱(chēng)作是"自引用指針",每當(dāng)創(chuàng)建了一個(gè)對(duì)象的時(shí)候,系統(tǒng)會(huì)自動(dòng)將this初始化指向當(dāng)前對(duì)象,而當(dāng)調(diào)用成員函數(shù)時(shí),”this“也會(huì)作為一個(gè)隱含參數(shù)傳入到函數(shù)中;
由于我們的程序時(shí)逐條執(zhí)行的,因此就不存在這同時(shí)對(duì)多個(gè)對(duì)象進(jìn)行操作的可能,那么在一段程序中,可能存在著多個(gè)同類(lèi)的對(duì)象,當(dāng)程序執(zhí)行到某個(gè)位置的時(shí)候,想要知道當(dāng)前正在操作的具體是哪個(gè)對(duì)象,就需要由this指針做指引,也就是說(shuō)this指針?biāo)赶虻木褪钱?dāng)前正在被調(diào)用的對(duì)象,例如以下代碼:
#includeusingnamespacestd;
classpeople{
??public:
????intage;
????stringname;
????intweight;
????voideat(){
???????weight++;?
????}??
};
intmain(){
??peopleXiao_Ming;
??Xiao_Ming.eat();
}
首先我們創(chuàng)建了一個(gè)對(duì)象“Xiao_Ming”當(dāng)我們調(diào)用其內(nèi)部的成員函數(shù)eat()時(shí),此時(shí)this指針指向了對(duì)象“Xiao_Ming”,此時(shí),”this“作為隱含參數(shù)傳入到eat( )當(dāng)中,我們雖然寫(xiě)作“weight++”而實(shí)際所執(zhí)行的是“this->weight++”或者是“Xiao_Ming.weight++”而對(duì)于靜態(tài)成員變量或靜態(tài)成員函數(shù)而言,其不屬于任何一個(gè)對(duì)象,故其類(lèi)型與this指針的類(lèi)型不匹配,自然無(wú)法進(jìn)行指向,故無(wú)法通過(guò)靜態(tài)成員函數(shù)來(lái)訪(fǎng)問(wèn)非靜態(tài)成員變量或函數(shù)(無(wú)this指針指向)
但是,靜態(tài)成員函數(shù)的好處在于,可以將其視為一個(gè)全局的函數(shù),我們可以通過(guò)類(lèi)名對(duì)其訪(fǎng)問(wèn),而不需要先創(chuàng)建一個(gè)對(duì)象再通過(guò)對(duì)象進(jìn)行訪(fǎng)問(wèn),如下所示:
#includeusingnamespacestd;
classpeople{
public:
????staticintnum_people;
????staticvoidshow_num{
??????cout<
5、友元
(1)友元的概念我們知道,類(lèi)中的成員變量或成員函數(shù)可以被我們用不同的訪(fǎng)問(wèn)修飾符進(jìn)行修飾的,其包括public、private、protected三種,其中public是共有的,任何對(duì)象或函數(shù)都可以對(duì)其進(jìn)行訪(fǎng)問(wèn),但是對(duì)于private和protected:
private:只能由類(lèi)內(nèi)成員函數(shù)、友元訪(fǎng)問(wèn);
protected:只能由類(lèi)內(nèi)成員函數(shù)、子類(lèi)函數(shù)、友元訪(fǎng)問(wèn);
因此,友元的作用就是幫助類(lèi)外其他函數(shù)或其他類(lèi),來(lái)訪(fǎng)問(wèn)類(lèi)內(nèi)私有或受保護(hù)的成員變量或函數(shù);
友元的關(guān)鍵字:friend
(2)類(lèi)外的全局函數(shù)作為類(lèi)的友元如果我們希望類(lèi)A外的函數(shù)a可以訪(fǎng)問(wèn)友元中的私有(受保護(hù))成員,那么我們應(yīng)該在類(lèi)A中聲明,a函數(shù)是類(lèi)A的友元,代碼如下:
#includeusing namespace std;
class A {
public:
int a;
private :
int b;
? ? // 友元函數(shù)的聲明
friend void fun();
};
//友元函數(shù)的類(lèi)外實(shí)現(xiàn)
void fun() {
A s;
s.a = 1;
? ? // 在全局函數(shù)fun()中訪(fǎng)問(wèn)了類(lèi)A中對(duì)象s的私有成員變量b
s.b = 2;
cout<< s.a + s.b<< endl;
}
在這段程序中,我們可以看到在類(lèi)A中,a是公共的,b是私有的,但是由于我們?cè)陬?lèi)A中聲明了,fun( )是類(lèi)A的友元函數(shù),因此即使fun是類(lèi)外的函數(shù),卻依舊可以通過(guò)創(chuàng)建對(duì)象來(lái)訪(fǎng)問(wèn)b
(3)類(lèi)A作為類(lèi)B的友元如果我們希望,類(lèi)B的任意成員函數(shù)可以訪(fǎng)問(wèn)類(lèi)A對(duì)象的私有成員,那么我們應(yīng)該聲明,類(lèi)B是類(lèi)A的友元,如下代碼所示:
#includeusing namespace std;
class A {
public:
int a;
private :
int b;
? ? // 友元函數(shù)的聲明
friend class B;
};
class B {
public:
void fun() {
A s;
s.a = 1;
? ? ? ? ? ? //在B的成員函數(shù)fun中訪(fǎng)問(wèn)了類(lèi)A中對(duì)象s的私有成員b? ?
s.b = 2;
cout<< s.a + s.b<< endl;
}
? ? ? ? void fun1() {
? ? ? ? A s;
? ? ? ? s.a = 1;
? ? ? ? ? ? //在B的成員函數(shù)fun1中訪(fǎng)問(wèn)了類(lèi)A中對(duì)象s的私有成員b
? ? ? ? s.b = 2;
? ? ? ? cout<< s.a * s.b<< endl;
? ? ? ? }
};
在這段程序中,我們將類(lèi)B做為類(lèi)A的友元,可以看到此時(shí)類(lèi)B的任意成員函數(shù)均可以訪(fǎng)問(wèn)類(lèi)A對(duì)像的私有成員變量
(4)類(lèi)B中的成員函數(shù)作為類(lèi)A的友元假如,我們只希望類(lèi)B中特定的成員函數(shù)可以去訪(fǎng)問(wèn)類(lèi)A的私有成員變量,那么我就不能將整個(gè)類(lèi)B作為類(lèi)A的友元,而是把特定的成員函數(shù)作為友元來(lái)聲明,如下代碼所示:
#includeusing namespace std;
class B {
public:
void fun();
};
class A {
? ? public:
? ? int a;
? ? private:
? ? int b;
? ? friend void B::fun();
};
void B::fun() {
A s;
s.a = 1;
s.b = 2;
cout<< s.a + s.b<< endl;
}
在這段代碼的寫(xiě)法上,有兩點(diǎn)值得我們注意:
我們將類(lèi)A的定義寫(xiě)在了類(lèi)B的下面,如果我們寫(xiě)作了下述代碼形式的話(huà),由于編譯器是順序編譯,因此fun( )函數(shù)的聲明應(yīng)該寫(xiě)在friend關(guān)鍵字聲明之前,否則會(huì)出現(xiàn)編譯器先看到了友元的聲明卻找不到函數(shù)的情況;
#includeusing namespace std;
class A {
public:
int a;
private:
int b;
friend void B::fun();
};
class B {
public:
void fun();
};
void B::fun() {
A s;
s.a = 1;
s.b = 2;
cout<< s.a + s.b<< endl;
}
其次,我們將fun( )函數(shù)的定義寫(xiě)在了類(lèi)外而不是和聲明寫(xiě)在一起,其原因與第一條類(lèi)似,如果我們將
代碼寫(xiě)作 如下形式的話(huà),會(huì)出現(xiàn)編譯器編譯fun( )的時(shí)候,尚不知道fun( )是類(lèi)A的友元,從而讓fun( )依舊無(wú)法訪(fǎng)問(wèn)類(lèi)A的私有成員變量;
#includeusing namespace std;
class B {
public:
void fun(){
? ? ? ? A s;
? ? ? ? s.a = 1;
? ? ? ? s.b = 2;
? ? ? ? cout<< s.a + s.b<< endl;
? ? ? ? }
};
class A {
public:
int a;
private:
int b;
friend void B::fun();
};
6、常成員變量和函數(shù)你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
當(dāng)前文章:CPP筆記——“類(lèi)和對(duì)象”-創(chuàng)新互聯(lián)
文章出自:http://weahome.cn/article/ccspgd.html