《C++程序設計教程》課件第3章_第1頁
《C++程序設計教程》課件第3章_第2頁
《C++程序設計教程》課件第3章_第3頁
《C++程序設計教程》課件第3章_第4頁
《C++程序設計教程》課件第3章_第5頁
已閱讀5頁,還剩136頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

3.1函數(shù)重載

3.2內聯(lián)函數(shù)

3.3引用

3.4友元

3.5名空間

本章要點

練習

3.1.1重載的概念

在C中,在同一個程序中聲明兩個同名函數(shù)是一種語法錯誤。而在C++中只要函數(shù)命名了不同的參數(shù)集,就允許用同一名字定義多個函數(shù)。C++的這種能力稱為函數(shù)重載。下面就用C++中提供的重載機制來實現(xiàn)本章開始時提出的求絕對值問題。

【例3-1】演示通過重載求x的絕對值。3.1函數(shù)重載通過重載的方法只用了一個函數(shù)名Fun,分別實現(xiàn)了求long、double和int類型數(shù)的絕對值。重載的優(yōu)點包括:對于不同的數(shù)據(jù)類型完成類似的操作;對于函數(shù)名的取名,可以見名知義,消除了在同一操作中使用不同函數(shù)名稱的情況;有助于輕松理解和調試代碼;使代碼維護變得更加容易。3.1.2匹配重載函數(shù)的順序

匹配重載函數(shù)是由編譯器完成的。編譯器通過函數(shù)名和其參數(shù)類型識別重載函數(shù)。編譯器在識別時,通過參數(shù)個數(shù)、參數(shù)類型和參數(shù)的次序確定被匹配的函數(shù),并對每一個函數(shù)的標識符進行特別編碼,以便實現(xiàn)匹配的唯一性。這一過程有教材稱為“名字改編”或“名字修飾”。在匹配重載函數(shù)時按優(yōu)先級進行,具體步驟為:先尋找是否有嚴格匹配(所謂嚴格匹配,就是同類型的匹配),然后通過內部數(shù)據(jù)轉換尋找是否有匹配。

對于兩個內部數(shù)據(jù),系統(tǒng)能自動尋找匹配。如若有l(wèi)ong和double形參,那么0、char和shortint等的實參,都是經內部數(shù)據(jù)轉換后可匹配的參數(shù)類型。

【例3-2】演示重載函數(shù)的內部轉換匹配,通過用戶定義的轉換尋找是否有匹配。其中要注意,對于帶有const修飾的內部轉換,只適用char*轉換為constchar*;對于其他非指針類型的情況,就認為是嚴格匹配。如在下面的代碼中,由于存在兩個嚴格匹配函數(shù)而出錯,去掉任何一個都可以。3.1.3對重載函數(shù)的要求

1.重載函數(shù)具有不同參數(shù)

重載函數(shù)至少在參數(shù)類型、參數(shù)個數(shù)或者參數(shù)順序上有所不同。C++的函數(shù)如果在參數(shù)類型、參數(shù)個數(shù)、參數(shù)順序上有所不同,則認為是不同的匹配,可以進行重載。如果僅僅只有函數(shù)的返回類型不同是不夠的,重載將不能實現(xiàn)。

在C++中這樣規(guī)定的理由就是要保證對重載的匹配只是針對單獨的運算符或函數(shù)調用,而與調用環(huán)境無關。下面是不合要求的重載函數(shù)的例子。

2.函數(shù)重載要在同一作用域內

函數(shù)重載要在同一個作用域內才能實現(xiàn)。對于幾個不同作用域中的函數(shù)是無法實現(xiàn)重載的。

【例3-3】函數(shù)重載與作用域的關系。

#include<iostream.h>

voidFun(intx)

{cout<<"int:"<<x<<endl;}運行結果:

double:100

顯然Fun(100)最好的匹配應當是Fun(intx),但是Fun(doubley)在main函數(shù)的局部作用域里,所以就優(yōu)先匹配Fun(doublex)。若去掉函數(shù)聲明,則兩個函數(shù)在同一作用域中,可實現(xiàn)重載,于是輸出int:100。

3.不要讓重載執(zhí)行不同的功能

重載的目的是:有助于輕松理解和調試代碼,使代碼維護變得更加容易,增加可讀性。因此讓重載執(zhí)行不同的功能不是好的編程風格。同名函數(shù)應該具有相同的功能。3.1.4重載的實現(xiàn)

重載可以發(fā)生在非成員函數(shù)之間,也可以發(fā)生在同一類的成員函數(shù)之間或構造函數(shù)之間??傊?,只要函數(shù)在同一作用域內,滿足重載的要求就可以進行重載。

【例3-4】通過建一個表格類來演示在構造函數(shù)之間進行重載。

【例3-5】有兩個類:Student和Tdate類,在這兩個類中都有兩個Set,其中一個是非成員函數(shù)Set。由于作用域的不同,Student類中的Set、Tdate類中的Set和非成員函數(shù)Set之間不能重載。在同一個類中的兩個Set是重載函數(shù)。運行結果:

Thedateis2007/08/24

generalfunction

4

上面演示了重載成員函數(shù)的執(zhí)行情況。重載成員函數(shù)既可以用對象名加分量運算符來訪問,也可以用指針加分量運算符來訪問。由于類名是成員函數(shù)名的一部分,因此一個類的成員函數(shù)與另一個類的成員函數(shù)或者普通函數(shù)即使同名,也不能實現(xiàn)重載。3.1.5重載的二義性

重載無需人工參與,在重載時由系統(tǒng)自動進行參數(shù)轉換并尋找匹配。若同時出現(xiàn)多個可匹配重載函數(shù),使得系統(tǒng)無法確定匹配哪個重載函數(shù),我們將這種現(xiàn)象稱為二義性。

要注意轉換的二義性。對于內部自動轉換是沒有優(yōu)先級的。假如實參是int,而形參同時有l(wèi)ong和double,int既可以自動轉換為long,也可以自動轉換為double,這就出現(xiàn)了二義性。解決方法是進行顯式轉換。在Fun(1);的調用中出現(xiàn)了錯誤。數(shù)字1可以自動轉換為double型,也可以自動轉換為long型,沒有優(yōu)先級。若要明確匹配long,可用1L明示。較好的方法是進行顯式轉換。顯式轉換的方法:Fun(long(1));或Fun(double(1));。

函數(shù)可以帶默認參數(shù),同樣,重載函數(shù)也可以帶默認參數(shù)。有了帶默認參數(shù)的函數(shù),在給我們帶來方便的同時也帶來了二義性。如果有一組重載函數(shù),由于它們都帶有默認參數(shù),那么即使是有不同參數(shù)個數(shù)的函數(shù),也有可能出現(xiàn)二義性。函數(shù)調用需要使用棧,這些工作就需要一些時間開銷。當函數(shù)體比較短小,功能簡單,又需要頻繁調用時,這種調用的系統(tǒng)開銷相對而言就較大。如果不用調用函數(shù)的方式,而直接將代碼寫入,使其按順序執(zhí)行,這樣就可以節(jié)省頻繁調用時所需的時間和空間。

3.2內聯(lián)函數(shù)在C中常用的方法是用預處理命令通過宏定義來實現(xiàn)。宏定義是命令,編譯器并不作語法檢查,它可能隱藏著危險,有時會得到錯誤的結果。例如,若有#definemultiply(x)x*x,則用y=multiply(5);可以得到y(tǒng)的值為25。若用z=multiply(2+3);,經過宏展開為2+3*2+3,z的值為11,這就出錯了。解決方法是加上括號:#definemultiply(x)(x)*(x)。在C++中,既要提高程序執(zhí)行的效率,又要減少麻煩,于是引入了內聯(lián)函數(shù)。內聯(lián)函數(shù)也稱內嵌函數(shù),它可以提高程序的運行效率,克服宏定義所帶來的弊端。所謂內聯(lián)或內嵌,就是將一段小程序經編譯后放到程序中使其成為一體。

引入內聯(lián)函數(shù),優(yōu)點是安全可靠、可讀性好、效率高,缺點是程序代碼比較長。3.2.1內聯(lián)函數(shù)的實現(xiàn)

1.一般內聯(lián)函數(shù)

內聯(lián)函數(shù)既可作為成員函數(shù),也可作為非成員函數(shù)。對于非成員的內聯(lián)函數(shù),我們稱它為一般內聯(lián)函數(shù)。例如:

inlineintFun(intx){returnx*x;} //定義內聯(lián)函數(shù)Fun

voidmain()

{inty;y=Fun(2+3);?} //y的值為25當編譯器在編譯時每遇到標有inline關鍵字的Fun函數(shù)后,就自動為它創(chuàng)建一段代碼,以便每次碰到該函數(shù)的調用都用相同的一段代碼來替換,提高效率與可讀性。

對于main中的y=Fun(2+3);語句,括號中的參數(shù)會強制完成正確的運算,同時對傳遞的參數(shù)將作類型檢查。若出現(xiàn)y=Fun(2.1+3.2f);或者y=Fun(2.1f+3.2f);的調用,馬上給出警告。因此,內聯(lián)函數(shù)既安全又可靠。要說明的一點是,內聯(lián)函數(shù)不同于其他函數(shù),在編譯時,凡是出現(xiàn)調用內聯(lián)函數(shù)處,總是用一段代碼取代它。本例中內聯(lián)函數(shù)的使用y=Fun(2+3);等價于{intx,y;y=(x=2+3,x*x);},這樣程序運行時就可順序執(zhí)行,免去了函數(shù)調用的一切步驟,既省略了函數(shù)調用的時間開銷,又避免了錯誤。內聯(lián)函數(shù)實際上是用代碼的空間來換取時間的。過多地使用內聯(lián)函數(shù)會增加程序長度,因此不宜多用。2.內聯(lián)成員函數(shù)

在C++中要使某一成員函數(shù)成為內聯(lián)函數(shù),有兩種方法實現(xiàn)。方法一,直接將該函數(shù)的實現(xiàn)放在類的定義中。對于只有幾行的函數(shù),可以在類的定義體內部定義。如果一個成員函數(shù)在類定義的內部定義,那么該成員函數(shù)將自動成為內聯(lián)函數(shù)。方法二,用inline聲明。在類定義體外部的成員函數(shù)要想成為內聯(lián)函數(shù),則必須明確地使用關鍵字inline。若要將某函數(shù)聲明為inline(內聯(lián)函數(shù)),則可在聲明或定義中加入inline,或者兩者都加入inline也可。

【例3-7】演示內聯(lián)函數(shù)的實現(xiàn)。3.2.2內聯(lián)函數(shù)的限制

內聯(lián)函數(shù)也是函數(shù),所以要遵循函數(shù)的規(guī)則,如,內聯(lián)函數(shù)必須在被調用之前聲明或定義,且僅聲明一次。

內聯(lián)函數(shù)是為提高程序運行效率而引入的,所以內聯(lián)函數(shù)中不能含有復雜的結構控制語句。程序員若將含有復雜的結構控制語句的函數(shù)聲明為內聯(lián)函數(shù),編譯器會自動拒絕,編譯時系統(tǒng)自動將該函數(shù)視同普通函數(shù)那樣生成函數(shù)調用代碼。也就是說,是否能真正成為內聯(lián)函數(shù),由程序員申請,編譯器決定。內聯(lián)函數(shù)中不能定義任何靜態(tài)變量,不能說明數(shù)組。遞歸函數(shù)不能作為內聯(lián)函數(shù)。一般來說,內聯(lián)函數(shù)是1~5行的短函數(shù),若語句較多也不要用內聯(lián)函數(shù)。語句較多編譯器不報錯,只是自動將它視為非內聯(lián)函數(shù)。3.3.1引用的概念

引用的概念就是給變量或對象取一個別名。我們現(xiàn)實生活中的人可以有別名,程序設計中的對象也可以有別名。在C++中給變量或對象取一個別名的方法稱為引用。建立引用的方法:

類型&別名=目標名;

例如:intx;int&n=x;先定義了一個整型變量x,接著給變量x取了一個別名n。

引用不是值,不占存儲空間。聲明引用時,目標的存儲狀態(tài)不會改變。因此引用只有聲明沒有定義。3.3引用3.3.2引用的操作

由于引用僅僅是對象的別名或化身,因此引用必須在聲明時初始化。這意味著從引用誕生起,它就是其他目標的別名,為別名而存在。從中也就告訴我們,若引用一個不存在的對象將是一個錯誤。

【例3-8】通過本例體會引用是別名,別名的行為就是目標的行為。#include<iostream.h>

voidmain()

{intx=3;int&a=x;

cout<<“x=”<<x<<“a=”<<a<<endl;

//引用作為目標的別名而使用

a=8;cout<<“x=”<<x<<“a=”<<a<<endl;

//對引用的改動就是對目標的改動

cout<<“&x=”<<&x<<“\t”<<“&a=”<<&a<<endl;

//引用的地址就是目標的地址

}

運行結果顯示x和a的值相同,地址也相同。3.3.3引用的利弊

也許我們正在思考這樣一個問題,好端端地為什么要多出一個引用,一個別名,別名做的事也算到原目標名的帳上,是否有點多此一舉。

1.引用的優(yōu)點

在C中,函數(shù)調用都是傳值調用,函數(shù)不能訪問調用程序中的原始變量,而只能訪問為它而創(chuàng)建的副本。由于引用是某一對象的別名,因此在函數(shù)調用中,引用傳遞的就是原來的變量或對象,而不是函數(shù)作用域內建立的變量或對象副本。引用作為參數(shù)傳遞時具有指針作為函數(shù)參數(shù)的效果。下面我們將對C++中引入引用的一些優(yōu)點作一介紹。

(1)引用具有指針的威力。引用傳遞的是原來的變量或對象,所以說引用具有指針的威力。引用具有傳值方式函數(shù)調用語法的簡單性與可讀性,但威力卻比傳值方式強。

(2)引用可以避免對象拷貝。在對象的傳遞中,為避免拷貝對象的開銷,可用引用的方式來傳遞對象。因為它僅是一個別名,不是另一個對象,不占有空間。因此引用作參數(shù)既節(jié)省空間,又節(jié)約時間。它隨目標而產生,隨目標的消亡而消亡。

(3)引用可以避免原始數(shù)據(jù)被修改。為了防止調用函數(shù)修改調用者的原始數(shù)據(jù),可以用傳遞常量引用的方式傳遞這些數(shù)據(jù)。在C++中通常用指針傳遞要修改的參數(shù),用引用常量的方法傳遞不要修改的參數(shù)。要想說明對常量的引用,只要把const限定符放在參數(shù)聲明的類型說明前即可。

【例3-9】演示引用的威力。#include<iostream.h>

voidmain()

{voidswap(int&,int&);

intx=5,y=6;

cout<<"beforeswap:\t"<<"x="<<x<<""<<"y="<<y<<endl;

swap(x,y);

cout<<"afterswap:\t"<<"x="<<x<<""<<"y="<<y<<endl;

}voidswap(int&u,int&v)

{inttemp;

temp=u;u=v;v=temp;

}

運行結果:

beforeswap: x=5y=6

afterswap: x=6y=5從運行結果可知,x、y的值被交換了。在voidswap(int&u,int&v)中用引用作函數(shù)參數(shù),這就意味著只要有參數(shù)傳過來,它就是該參數(shù)的別名。因為u是x的別名,v是y的別名,對u、v的改變就是對x、y的改變。

2.引用存在的問題

任何事物都是一分為二的。在引用給我們帶來方便的同時也帶來了新的問題。下面就對可能出現(xiàn)的錯誤進行分析,以便在采用引用時權衡利弊。

(1)可能隱藏錯誤。在函數(shù)調用時,我們曾說過是拷貝調用,不用擔心參數(shù)被修改的問題。然而有了引用后問題就出來了?,F(xiàn)通過下面的代碼來體會一下危險性。

intx=6;inty=8;

swap(x,y);對于swap(x,y);調用,沒有看到被調函數(shù)原型之前,就不能確定實參x和y是否會在被調函數(shù)中被修改。請看下面的兩個函數(shù)。

若被調函數(shù)是:

voidswap(intu,intv){intt=u;u=v;v=t;}

在函數(shù)調用時,通過參數(shù)拷貝,在swap中沒有能力改變實參x和y的值,即x和y不會被交換。

若被調函數(shù)是:

voidswap(int&u,int&v) //x和y被交換

{intt=u;u=v;v=t;}在被調函數(shù)中的參數(shù)是引用,一旦接收到實參x和y,形參u和v就分別成為x和y的別名。那么對別名的改變就是對目標名的改變,實參x和y的值就可以被改變。

綜合上面的分析可知引用的危險性,即在被調函數(shù)中可能隱藏著主調函數(shù)中參數(shù)被修改的可能性。

(2)可能引起編譯錯誤。使用引用后,重載函數(shù)時可能引起編譯錯誤。從上面的分析可知,同一函數(shù)swap的調用有兩種可能的匹配方式,若兩個被調函數(shù)同時出現(xiàn),系統(tǒng)就不知道該匹配哪一個,這就引起了編譯錯誤。voidswap(intx,inty){/*………*/}

voidswap(int&a,int&b){/*………*/}

voidmain()

{intx=6;inty=8;

swap(x,y);

}

對于swap(x,y)的函數(shù)調用,上面兩個swap函數(shù)的參數(shù)雖然一個是變量,一個是引用,但都是整型參數(shù),是同一類型。由于不能從函數(shù)調用中判斷是值傳遞還是引用傳遞,因此無法確定swap(x,y);匹配哪一個函數(shù)。3.3.4引用規(guī)則

在建立引用時,是對同類數(shù)據(jù)類型的變量或對象的引用,不是對數(shù)據(jù)類型的引用。若一個變量聲明為Type&,引用時它必須用Type類型的變量或對象初始化,或用能轉換成Type類型的(變量或)對象初始化。例如,若有inta[8];int&b=a;則出錯,因為對整型的引用,只能用整型變量初始化,不能用數(shù)組名。數(shù)組名是地址,是常量。

(1)在引用變量或對象時可以引用一個相同數(shù)據(jù)類型的變量或對象。例如:doublex,temp;floaty;

double&t=temp; //ok

double&t=x; //error,引用不能重名

double&z=y;

//error,引用了不同類型的變量

inta;int*&q=&a; //error,不能取一個地址的別名

float&w=float; //error,不能對類型引用

float&v=8.8f; //error,變量不能作為數(shù)據(jù)的別名

若是對常量的引用,則可以用constfloat&v=8.8f,即v就是8.8的別名。

(2)在引用指針變量時可以引用一個同類型的指針變量。例如:

int*p;inta;p=&a;

int*&q=p; //ok

即使p還沒有指向也可以引用。例如:

int*p;int*&q=p; //ok

該句的語義是將int*的引用q初始化為p。雖然此時p還無指向,但也是引用的初始化。

inta=8;q=&a; //ok,對于指針變量的引用,可改變指向

由于q是p的別名,因此它們是同一個指針,現(xiàn)在q指向a,當然p也就指向a。

(3)不能建立引用數(shù)組。數(shù)組是某個數(shù)據(jù)類型元素的集合,數(shù)組名表示該集合空間的起始地址,而不是某個數(shù)據(jù)類型的變量或對象。如果有inta[8];int&b[8]=a;,則出錯。

(4)若將引用作為類的數(shù)據(jù)成員,則必須初始化。例如:3.3.5指針和引用的區(qū)別

指針和引用有相同點,同時也存在著差別,主要表現(xiàn)在如下幾個方面。第一,操作方式不同。指針是間接訪問,而引用是直接訪問。例如:int*p,a;p=&a;*p=8;通過p間接訪問a空間。intb;int&q=b;q=9;由q直接訪問b空間。第二,指針本身是一個變量,可以不初試化,而引用是別名,必須初試化;指針可以再指向其他變量,而引用一旦確立,就不能再作為其他變量的別名。3.4.1友元函數(shù)

在C++中提供了一個稱為友元的函數(shù),該函數(shù)就是類的朋友。友元函數(shù)不是類的成員函數(shù),而是普通的C++函數(shù),但它可以訪問類的保護或私有成員,方便編程,提高效率。

一個普通函數(shù)可以是某類的友元,一個類的成員函數(shù)也可以是另一個類的友元,該函數(shù)就稱為友元函數(shù)。3.4友元

1.友元函數(shù)聲明

友元要在類中聲明。因為友元不是類的成員,所以它不受其所在類的聲明區(qū)域的影響,聲明時既可以放在public區(qū),也可以放在private區(qū)或protected區(qū),結果是一樣的。友元函數(shù)的定義必須放在類的外部,可以與該類成員函數(shù)的定義放在一起。

2.應用場合

普通函數(shù)需要訪問類的保護或私有成員時,若沒有友元機制,則只能將類的數(shù)據(jù)成員聲明為公有的,那么任何函數(shù)都可以無約束地訪問它。友元函數(shù)就是為了能在類之外訪問類的保護或私有成員,而與類建立朋友關系的函數(shù)。一般在下列三種情況下要用到友元函數(shù):

(1)要通過重載運算符實現(xiàn)某些類型對象的運算(將在第5章中介紹)。

(2)要簡化創(chuàng)建某些類型的I/O函數(shù)的過程(將在第8章中介紹)。

(3)要將某些類型的特征進行互相關聯(lián)或比較時。

3.使用方法

首先進行友元函數(shù)聲明,然后在該類之外完成友元函數(shù)的實現(xiàn)。聲明方法是在類中按聲明一個普通函數(shù)的方法聲明函數(shù),并在該函數(shù)的類型前標上關鍵字friend,這時函數(shù)就成了該類的友元。在友元函數(shù)的實現(xiàn)部分,函數(shù)頭不再需要加關鍵字friend,在函數(shù)體內完成所需功能。

【例3-10】若有凳子和桌子類,現(xiàn)要求比較顏色是否一樣。本例中定義有兩個全局對象,用來演示普通函數(shù)作為類的友元是如何訪問對象的保護成員的。運行結果:

DeskandBencharedifferentcolor

在本例的兩個類中,友元函數(shù)的聲明位置不同,效果是一樣的。本例實現(xiàn)了在一個普通函數(shù)中,將兩個類的顏色特征進行相互比較的功能。將普通函數(shù)Check同時聲明為Desk和Bench類的友元,那么在Check中就可以訪問這兩個類的所有成員。訪問方法如同訪問公有成員一樣,即對象名.成員。

【例3-11】教師類中的成員函數(shù)Check和Display是學生類的友元函數(shù),它們能訪問學生的學號和課程,而教師類中的Test函數(shù)無此特權。通過本例演示一個類的成員函數(shù)作為另一個類的友元函數(shù)的實現(xiàn)方法。

#include<iostream.h>

classStudent; //Teacher用到Student類作參數(shù),故作聲明

classTeacher

{public:運行結果:

num=203course=4.5

本例演示了聲明和定義友元函數(shù)的方法。因為教師類中有成員函數(shù)是學生類的友元函數(shù),所以必須將Teacher類的定義放在Student類的定義之前。

在本例中又有學生類的引用作函數(shù)參數(shù),如Teacher::Check(Student&),因此就要在教師類的定義前加上學生類的聲明。聲明方法是:關鍵字class加上類名,如上面的classStudent;所示。

【例3-12】該例的描述中,將Teacher類的成員函數(shù)Fun聲明為Student友元,又將普通函數(shù)Display和Show聲明為Student友元。

#include<iostream.h>

classStudent; //類聲明

classTeacher

{public:

voidassignGreads(int);

voidFun(Student&a);//以Student類的引用作為形參

private:

intnoofstudent;

};運行結果:

score=78

Newscore=88

Newscoreis:88

Thescoreis:0

該例同時演示了成員函數(shù)和普通函數(shù)作為友元函數(shù),訪問類中保護或私有成員的方法。從中也進一步得知友元函數(shù)的使用要慎重,因為它會破壞類的封裝性。

4.關于友元的說明

在聲明A類的成員函數(shù)為B類的友元時,要將A類的定義放在B類的定義之前。若A類的成員函數(shù)的參數(shù)中有C類的類型,則在A類的定義之前加上C類的聲明或C類的定義,即要實現(xiàn)可知性。友元不是成員函數(shù),它是類的朋友。既然是朋友,它就能訪問類的全部成員。友元是單向的。如僅僅A是B的友元,則A能訪問B類的全部成員,而B卻不能訪問A類的成員。即友元關系是“給予”,而不是“索取”。

友元機制在給我們帶來好處的同時也產生了新的不足。正因為它可以訪問類的保護或私有成員,而破壞了類的封裝性。因此我們說,友元破壞了類的封裝,在使用它時,要權衡利弊。3.4.2友元類

可以將整個類聲明為另一個類的友元,該類就稱為友元類或友類。友類中的每個成員函數(shù)都可以訪問另一類中的保護或私有成員,這就減少了將所有成員函數(shù)都聲明為友元的麻煩。

【例3-13】有Leader、Teacher和Student三個類,要求實現(xiàn)Leader中的object是Teacher的友元函數(shù),可訪問Teacher,Teacher是Student類的友類。運行結果:

score=78 //調用Student類的成員函數(shù)后得

Newscore=88 //調用Teacher類的成員函數(shù)后得

Numberofstudent35 //調用Leader類的成員函數(shù)后得

從運行結果來看,該例實現(xiàn)了有效訪問。如最后一行的輸出結果是調用Leader類的成員函數(shù),在該成員函數(shù)中訪問了Teacher類中的private成員noofstudent。

在上面的例子中,Teacher類是Student類的友類,Teacher類中的所有成員函數(shù)都可以訪問Student類中的私有或保護成員;反之,Student類中的成員函數(shù)卻不可以訪問Teacher類中的私有或保護成員。3.4.3互為友類

若兩個類之間需要相互訪問,可以聲明互為友類。這樣兩個類中的所有成員函數(shù)就都可以互訪。這如同我們生活中的從個人朋友關系,發(fā)展到家庭之間的友誼而相互友好往來一樣。

【例3-14】教師類與學生類互為友類。教師可修改學生的成績,也可調整學時數(shù)。學生也可訪問在校生總數(shù)。運行結果:

15000

score=87

hours=110

Numberofstudent:150003.5.1概念與作用

在C++中,可以將一些對象名限制在以某一標識符命名的空間內,該被命名的空間稱為名空間。使用名空間是為了解決代碼名的重復和排斥問題。名空間機制允許我們封裝名字,否則名字可能會污染全局名空間(pollutetheglobalnamespace)。一般來說,當程序員希望自己的代碼被外部軟件開發(fā)部門使用時,才使用名空間。C++提供了一種機制,可以把相關數(shù)據(jù)、函數(shù)等組織到一個獨立的名空間里。3.5名空間3.5.2實現(xiàn)方法

名空間的實現(xiàn)方法是:

namespace標識符{所有被封裝在以該標識符命名的名空間內的名字聲明}

例如,模塊My_Newspace和You_Newspace的用戶界面可以用下面的方法聲明和使用:

//My_Newspace.h

//頭文件名

#include<iostream.h>

namespaceMy_Newspace

{classArray關鍵字namespace后面的名字My_Newspace標識了一個名空間,它獨立于全局名空間,我們可以在里面放一些希望在函數(shù)或類之外聲明(定義)的實體。名空間不改變其中聲明的意義,只改變它們的可見性。

若要定義一個對象,可以用:My_Newspace::Arrayma;You_Newspace::Arrayia;。這樣一來,ma是我公司類的對象,ia是你公司類的對象。這樣就避免了都使用相同名字Array而引發(fā)的名字沖突。

程序員希望訪問名空間內聲明的名字時不加限定修飾符,這時可以使用using指示符,使名空間內的所有聲明都可見。

using與namespace都是關鍵字。usingnamespaceMy_Newspace;的語義是將模塊My_Newspace中的所有名字統(tǒng)統(tǒng)放入全局名空間內。也就是說,所有在該名空間里聲明的名字都成為本文件的全局名字。其中要注意兩個問題:第一,被使用的名空間必須已經被聲明了,否則會引起編譯錯誤;第二,不要再聲明與已可見名字相同的全局變量。為避免沖突,using聲明還可以實現(xiàn)有選擇的可見性。3.5.3嵌套名空間

用戶聲明的名空間允許嵌套,從而成為嵌套名空間。例如:

namespaceMy_NameA

{constdoublepi=3.1416;

namespaceMy_NameB若要聲明類名字,可以用:My_NameA::My_NameB::Array。若要聲明類成員名字,可以用:voidMy_NameA::My_NameB::Array::Set。3.5.4std名空間

為了防止標準C++庫的組件污染用戶的全局名空間,所有C++庫的組件都封裝在一個被稱為std的名空間內。使用時可以先用#include<iostream>,再用using指示符,使得C++庫內在名空間std中聲明的組件對于我們的程序可見。在本例中endl已可見,可以直接使用,而cout并未可見,所以要加上空間名。若去掉usingstd::endl;聲明,要實現(xiàn)同樣的效果就得聲明如下:

#include<iostream>

voidmain()

{std::cout<<“namespace”<<std::endl;

}本例中用到了#include<iostream>。<iostream.h>與<iostream>的區(qū)別是:iostream.h是早期C++中的使用方式,這些老式的頭文件只是將標準庫定義的功能引入全局名空間,而不是把名字引入名空間std。若用戶的系統(tǒng)還不支持新方式,仍可以用老方式,只要加上?.h,同時去掉對名空間std的使用即可。3.5.5匿名名空間

在C++中可以使用不給出名字的名空間,使得在該空間內聲明的變量或函數(shù),在其他文件中不可以訪問。例如:

//頭文件,fun.h

voidShow();

doubleFun(intc);

//實現(xiàn)文件,fun.cpp

#include“fun.h”

#include<iostream.h>intk; //定義該文件中的全局變量

namespace //匿名名空間

{doublen; //成員只能在本文件中使用,或稱文件

數(shù)據(jù)

intm=0; //文件數(shù)據(jù)

voidSet(){n=8;} //文件函數(shù)

}

voidShow(){cout<<k<<endl;}//全局函數(shù)

doubleFun(intc)

{Set(); //它只能在本文件中使用

returnn+c;對于某一文件的全局變量,在另一文件中只要對其進行擴展聲明,便可使用該變量。而若將某名字放在未命名的名空間內,那么其他文件就不能訪問它了。上例中,函數(shù)Fun()在未命名的名空間內,它只能在本文件中被訪問,不能被其他文件訪問。將某一名字的使用范圍限制在一個文件中,優(yōu)點是其他文件就可以再一次使用這個相同的名字,兩個文件相互不干擾?!?重載適用于在不同類型的函數(shù)上作不同運算而用相同名的情況。

●?C++的函數(shù)如果在參數(shù)類型、參數(shù)個數(shù)、參數(shù)順序上有所不同,則認為是不同的匹配,可以進行重載。

●?重載的目的是:更方便理解和調試代碼,使代碼維護變得更加容易,增加可讀性。

●?不要讓重載執(zhí)行不同的功能,同名函數(shù)應該具有相同的功能。

●?函數(shù)重載時要考慮到實現(xiàn)匹配的唯一性。本章要點●?內聯(lián)函數(shù)主要用來提高程序的運行效率,克服宏定義使用#define所帶來的弊端。

●?將函數(shù)的實現(xiàn)放在類的定義中,那么該成員函數(shù)將自動成為內聯(lián)函數(shù)。

●?內聯(lián)函數(shù)實際上是用空間換取時間。

●?內聯(lián)函數(shù)是1~5行的小函數(shù),若語句較多就不要用內聯(lián)函數(shù)。

●?在C++中給變量或對象取一個別名的方法稱為引用。

●?引用不是值,不占用存儲空間,因此引用只有聲明沒有定義。●?在建立引用時,只能對同類數(shù)據(jù)類型的變量或對象進行引用。

●?引用傳遞的是原來的變量或對象,所以說引用具有指針的作用。

●引用與指針有很大的差別,指針是個變量,可以把它再指向其他地址,然而建立引用時必須初始化且不能再把它取為另一對象的別名。

●?傳遞引用不生成副本,返回引用時也不生成值的副本,可見引用對空間無要求。

●?引用可能隱藏錯誤,在使用中要引起注意。

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論