版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第六章 程序結(jié)構(gòu)16.1對(duì)象的作用域與可見(jiàn)性 作用域是指標(biāo)識(shí)符的作用范圍或有效范圍,可見(jiàn)性是從對(duì)標(biāo)識(shí)符引用的角度來(lái)談的概念,若標(biāo)識(shí)符在某處可見(jiàn),則就可以在該處引用該標(biāo)識(shí)符。這里所說(shuō)的標(biāo)識(shí)符主要是指變量名或者對(duì)象名。16.1.1 對(duì)象的作用域例子#include int id01=3;void main()int id=5; int id; id=7; cout id= id endl; /輸出7 cout id= id endl; /輸出5 cout id01 endl; /輸出31.函數(shù)原形的作用域函數(shù)原形的作用域是指函數(shù)原型中標(biāo)識(shí)符形參的作用范圍,其作用域始于函數(shù)原形的左括號(hào)“(”,結(jié)束于
2、函數(shù)原形聲明的右括號(hào)“)”。例如,設(shè)有下列原型聲明:double Area(double radius);等價(jià)形式: double Area(double);radius的作用域僅在函數(shù)的左右括號(hào)之間,不能用于程序正文其它地方,因而radius參數(shù)可有可無(wú),省略它,也不會(huì)影響程序的編譯效果,但是,考慮到可讀性,還是在函數(shù)原形中給出形參說(shuō)明比較好。需要說(shuō)明的是,這里函數(shù)原形的作用域是針對(duì)函數(shù)聲明中的對(duì)象形參而言的,而不是指函數(shù)實(shí)現(xiàn)中的對(duì)象形參。2.塊作用域塊作用域是指在塊中聲明的標(biāo)識(shí)符,其作用域自聲明處起,一直到塊結(jié)束為止。由于該作用域的范圍具有局部性,所以有些文獻(xiàn)也把它叫作局部作用域。例如:#
3、includevoid fun(int x) /x的作用域從此處開(kāi)始 int y=x; /y的作用域從此處開(kāi)始 ciny; if (y0) int z; /z的作用域從此處開(kāi)始 z=x+y; /z的作用域到此處結(jié)束 /x和y的作用域到此處結(jié)束這里,y和z都具有塊作用域,并且是不同的塊作用域。所謂塊是指用一對(duì)花括號(hào)“”和“”括起來(lái)的一段程序。在本例中,函數(shù)體是一個(gè)塊,if語(yǔ)句后的分支部分又是一個(gè)較小的塊,二者是包含的關(guān)系。3.類(lèi)作用域類(lèi)的作用域是指類(lèi)的聲明中一對(duì)花括號(hào)所形成的作用范圍,簡(jiǎn)稱(chēng)類(lèi)域。每一個(gè)類(lèi)都具有該類(lèi)的類(lèi)域,該類(lèi)的成員局部于該類(lèi)所屬的類(lèi)域中,一個(gè)類(lèi)的某個(gè)成員可以引用該類(lèi)的其他成員,或
4、者說(shuō)類(lèi)的某個(gè)成員對(duì)同一類(lèi)的其他成員具有無(wú)限制的訪問(wèn)權(quán)。在類(lèi)作用域之外,對(duì)類(lèi)成員的訪問(wèn)一般是不允許的,或者要受特殊的規(guī)則的限制(如使用友元函數(shù))。在C+中,由于類(lèi)中成員的特殊訪問(wèn)規(guī)則,使得類(lèi)中成員的作用域變得比較復(fù)雜。具體地講,某個(gè)類(lèi)A的某個(gè)成員M在下情況下具有類(lèi)A的作用域:1)該成員M出現(xiàn)在該類(lèi)的某個(gè)成員函數(shù)中,并且該成員函數(shù)沒(méi)有定義同名標(biāo)識(shí)符。2)該類(lèi)A的某個(gè)對(duì)象的該成員M的表達(dá)式中。例如,設(shè)x是A的對(duì)象,則在表達(dá)式x.M中。3)在該類(lèi)A的某個(gè)指向?qū)ο笾羔樀脑摮蓡TM的表達(dá)式中。例如,設(shè)pt一個(gè)指向A類(lèi)對(duì)象的指針,則在表達(dá)式pt-M中。4)在使用作用域操作符所限定的該成員中。例如,在表達(dá)式A:
5、M中。需要強(qiáng)調(diào)說(shuō)明的是,類(lèi)作用域不同于文件域,在類(lèi)作用域中定義的變量不能使用auto、register和extern等修飾符,只能用static修飾符,而定義的函數(shù)也不能用extern修飾符。另外,在類(lèi)作用域中的靜態(tài)成員和成員函數(shù)還具有外部的連接屬性。一般說(shuō)來(lái),類(lèi)作用域介于文件作用域和塊作用域之間,由于類(lèi)作用域問(wèn)題比較復(fù)雜,只能根據(jù)實(shí)際情況,具體問(wèn)題具體分析。4.文件作用域不在前述各個(gè)作用域中出現(xiàn)的聲明,具有文件作用域,這樣聲明的標(biāo)識(shí)符的作用域開(kāi)始于聲明點(diǎn),結(jié)束于文件尾。由此可以看出,文件作用域是在所有函數(shù)之外說(shuō)明的。一般來(lái)說(shuō),在文件開(kāi)始所定義的全局標(biāo)識(shí)符就具有全局作用域,從這個(gè)意義上說(shuō)文件作
6、用域也叫全局作用域。不同位置定義的同名標(biāo)識(shí)符有不同的作用域,要注意區(qū)別。16.1.2對(duì)象的可見(jiàn)性可見(jiàn)性是從對(duì)標(biāo)識(shí)符的引用的角度來(lái)談的概念,如果標(biāo)識(shí)符在某處可見(jiàn),則表示在該處可以引用該標(biāo)識(shí)符。作用域指的是標(biāo)識(shí)符的有效范圍,而可見(jiàn)性是分析在某個(gè)位置標(biāo)識(shí)符的有效性。在作用域中,文件作用域最大,接著依次是類(lèi)作用域和塊作用域,作用域的一般關(guān)系見(jiàn)圖6.1所示??梢?jiàn)性表示從內(nèi)層作用域向外層作用域“看”時(shí)能看見(jiàn)什么,可見(jiàn)性和作用域之間有著緊密的聯(lián)系。塊作用域類(lèi)作用域文件作用域圖6.1 作用域關(guān)系圖 作用域可見(jiàn)性的一般如下:標(biāo)識(shí)符應(yīng)聲明在先,引用在后。在同一作用域中,不能聲明同名的標(biāo)識(shí)符。如果某個(gè)標(biāo)識(shí)符在外層中
7、聲明,且在內(nèi)層中沒(méi)有同一標(biāo)識(shí)符的聲明,則該標(biāo)識(shí)符在內(nèi)層可見(jiàn)。對(duì)于兩個(gè)嵌套的作用域,如果在內(nèi)層作用域內(nèi)聲明了與外層作用域中同名的標(biāo)識(shí)符,則外層作用域的標(biāo)識(shí)符在內(nèi)層不可見(jiàn)。 例6.1 作用域與可見(jiàn)性示例。#includeusing namespace std;int x; /定義全局變量,具有文件作用域void main() x=3; /給文件作用域的變量賦初值3 int x; /子塊中定義局部變量,具有塊作用域 x=5;coutx=xendl; /輸出5 coutx=x; /輸出3 在本例中,主函數(shù)外聲明的變量x具有文件作用域,其有效作用范圍是整個(gè)源程序文件。在主函數(shù)開(kāi)始處給文件作用域的變量賦初
8、值3接著在子塊中聲明同名變量并賦初值5,第一次輸出結(jié)果為5,這是因?yàn)榫哂袎K作用域的變量把具有文件作用域的同名變量給屏蔽掉了,即具有文件作用域的變量在塊中變得不見(jiàn)。當(dāng)程序運(yùn)行到子塊結(jié)束后,第二次輸出的結(jié)果才是具有文件作用域的變量值3。需要說(shuō)明的是,在局部變量的作用域內(nèi),可用使用作用域操作符“:”對(duì)隱藏的同名全局變量進(jìn)行訪問(wèn)。例6.2 作用域操作符使用示例。#includedouble a; /全局變量int b; /全局變量enum Red,White,Blue; /全局枚舉void main() int a; /局部變量 double b; /局部變量 enumBlue,White,Red;
9、/局部枚舉a=5; /給局部變量賦值 :a=2.5; /給全局變量賦值 b=4.5; :b=4; coutaendl; cout:aendl; coutsizeof(b)endl;/顯示雙精度浮點(diǎn)數(shù)占用的內(nèi)存數(shù) coutsizeof(:b)endl;/顯示整型數(shù)占用的內(nèi)存數(shù) cout(int)Blueendl;/顯示enum型局部值 cout(int):Blueendl;/顯示enum型全局值程序運(yùn)行結(jié)果: 5 2.5 8 4 0 216.2對(duì)象的生存期無(wú)論是簡(jiǎn)單變量還是類(lèi)的對(duì)象都有產(chǎn)生和結(jié)束的時(shí)刻。變量或?qū)ο髲漠a(chǎn)生到結(jié)束的這段時(shí)間就是它的生存期。在對(duì)象生存期內(nèi),對(duì)象將保持它的值,直到其被更新
10、為止。1.靜態(tài)生存期若對(duì)象的生存期與程序的運(yùn)行期相同,則稱(chēng)該對(duì)象具有靜態(tài)生存期。下面兩種情況的對(duì)象具有靜態(tài)生存期:1)在文件作用域中聲明的對(duì)象具有這種生存期。2)在函數(shù)內(nèi)部聲明靜態(tài)生存期對(duì)象,要冠以關(guān)鍵字static 。 由此可見(jiàn),只有文件作用域中聲明的對(duì)象或塊作用域中用關(guān)鍵字static聲明的對(duì)象才具有靜態(tài)生存期。例6.3 靜態(tài)生存期示例。#includeint x=5; /文件作用域void main() coutx=xendl; 在本例中,變量x具有靜態(tài)生存期。2.動(dòng)態(tài)生存期上述兩種情況除外的對(duì)象都具有動(dòng)態(tài)生存期。塊作用域中直接聲明的對(duì)象是動(dòng)態(tài)生存期的對(duì)象,習(xí)慣也稱(chēng)作局部生存期對(duì)象。動(dòng)態(tài)
11、生存期對(duì)象開(kāi)始于程序聲明點(diǎn),結(jié)束于命名該標(biāo)識(shí)符的作用域結(jié)束處。例6.4 動(dòng)態(tài)生存期示例。#includevoid fun();void main() fun(); fun();void fun() static int a=1; int i=5; a+; i+; couti=i,a=aendl; 在本例中,變量a具有靜態(tài)生存期,變量x具有動(dòng)態(tài)生存期。根據(jù)生存期的不同,可以把對(duì)象劃分成如下三種:1)局部對(duì)象:當(dāng)對(duì)象被聲明時(shí)調(diào)用構(gòu)造函數(shù),該對(duì)象被創(chuàng)建,當(dāng)程序退出定義該對(duì)象所在的函數(shù)體或程序塊時(shí),調(diào)用析構(gòu)函數(shù),釋放該對(duì)象。2)靜態(tài)對(duì)象:當(dāng)程序第一次執(zhí)行所聲明的靜態(tài)對(duì)象時(shí),該對(duì)象被創(chuàng)建,當(dāng)程序結(jié)束時(shí),
12、該對(duì)象被釋放。3)全局對(duì)象:當(dāng)程序開(kāi)始時(shí),調(diào)用構(gòu)造函數(shù)創(chuàng)建該對(duì)象,當(dāng)程序結(jié)束時(shí)調(diào)用析構(gòu)函數(shù)釋放該對(duì)象。局部對(duì)象是被定義在一個(gè)函數(shù)體或程序塊內(nèi)的,它的作用域小,生存期也短,這種對(duì)象具有塊作用域和動(dòng)態(tài)生存期。靜態(tài)對(duì)象是被定義在一個(gè)文件中,它的作用域從定義時(shí)起到文件結(jié)束時(shí)止。它的作用域比較大,它的生存期也比較大,這種對(duì)象具有靜態(tài)生存期。全局對(duì)象是被定義在某個(gè)文件中,而它的作用域卻在包含該文件的整個(gè)程序中,它的作用域是最大的,它的生存期也是長(zhǎng)的,該對(duì)象具有靜態(tài)生存期。例6.5 對(duì)象的靜態(tài)、動(dòng)態(tài)生存期示例。#includeusing namespace std;class Time /聲明時(shí)間類(lèi)priv
13、ate:int hour,minute,second; /私有數(shù)據(jù)成員public: /外部接口Time();void SetTime(int h,int m,int s);/三個(gè)形參具有函數(shù)原形作用域void ShowTime();Time();/時(shí)鐘類(lèi)成員函數(shù)定義Time:Time() /構(gòu)造函數(shù)hour=0;minute=0;second=0;void Time:SetTime(int h,int m,int s) /設(shè)置時(shí)間成員函數(shù)hour=h;minute=m;second=s;void Time:ShowTime() /顯示時(shí)間成員函數(shù)couthour:minute:seconde
14、ndl;Time g_time; /聲明全局對(duì)象g_time,具有靜態(tài)生存期void main() coutOutput time1=;/引用具有文件作用域的對(duì)象g_timeg_time.ShowTime();/對(duì)象的成員函數(shù)具有類(lèi)作用域coutendl;g_time.SetTime(10,29,29);Time l_time(g_time);/聲明局部對(duì)象l_time,具有動(dòng)態(tài)生存期coutOutput time2=;/引用具有塊作用域的對(duì)象l_timel_time.ShowTime();coutendl;程序運(yùn)行結(jié)果:Output time1=0:0:0Output time2=10:29
15、:29在本例程序中,包含了各種作用域類(lèi)型的變量或?qū)ο?,其中時(shí)間類(lèi)聲明中的成員函數(shù)SetTime的三個(gè)形參具有函數(shù)原形作用域,對(duì)象l_time等具有塊作用域,時(shí)間類(lèi)的數(shù)據(jù)成員和成員函數(shù)具有類(lèi)作用域,對(duì)象g_time具有文件作用域。在主函數(shù)中,對(duì)象及其公有成員都是可見(jiàn)的。在主函數(shù)之外聲明的對(duì)象g_time具有靜態(tài)生存期、文件作用域,該對(duì)象是通過(guò)構(gòu)造函數(shù)對(duì)其作初始化。在主程序中,首先輸出時(shí)間0:0:0;接著將對(duì)象g_time的時(shí)間設(shè)置為10:29:29;然后聲明具有塊作用域的對(duì)象l_time,它具有動(dòng)成生存期,并用g_time對(duì)其作初始化,此時(shí)調(diào)用默認(rèn)的拷貝函數(shù)將g_time對(duì)象的數(shù)據(jù)成員值賦給l_
16、time,因此對(duì)象l_time和g_time具有完全相同的數(shù)據(jù),輸出對(duì)象l_time的時(shí)間為10:29:29。6.3對(duì)象的存儲(chǔ)類(lèi)型簡(jiǎn)單變量具有以下4種存儲(chǔ)類(lèi)型:auto:采用堆棧方式分配內(nèi)存空間,屬于暫時(shí)性存儲(chǔ),其存儲(chǔ)空間可以被若干變量多次覆蓋使用。register:存儲(chǔ)在通用寄存器中。extern:在所有函數(shù)和程序段中都可引用。static:在內(nèi)存中以固定地址存放,在整個(gè)程序運(yùn)行期間都有效。其中,static關(guān)鍵字除用于簡(jiǎn)單變量外,還可用于將類(lèi)的成員聲明為靜態(tài)成員,以解決同一個(gè)類(lèi)的不同對(duì)象之間的數(shù)據(jù)和函數(shù)的共享問(wèn)題。但各種形式的數(shù)據(jù)共享又會(huì)不同程度地破壞數(shù)據(jù)安全。因此,對(duì)于既需要共享、又需要
17、防止改變的數(shù)據(jù)應(yīng)該聲明為常量進(jìn)行保護(hù),因?yàn)槌A吭诔绦蜻\(yùn)行期間是不可改變的。聲明對(duì)象時(shí),可以使用const進(jìn)行修飾,稱(chēng)之為常量對(duì)象。本節(jié)首先講解const修飾的常量對(duì)象。然后介紹靜態(tài)成員的使用。前者用于實(shí)現(xiàn)共享數(shù)據(jù)的保護(hù),后者用于實(shí)現(xiàn)類(lèi)對(duì)象之間的數(shù)據(jù)或函數(shù)的共享。6.3.1 用const修飾的常量對(duì)象用const修飾的常類(lèi)型的變量或?qū)ο蟊仨氝M(jìn)行初始化,而且不能被更新。1.常對(duì)象常對(duì)象是指對(duì)象常量,常對(duì)象必須進(jìn)行初始化,且不能被更新。常對(duì)象聲明格式如下:類(lèi)名 const 或者const 例如:class A public: A(int i,int j) x=i; y=j; .private: in
18、t x,y;A const a(1,2); /a是常對(duì)象,不能被更新 與基本數(shù)據(jù)類(lèi)型中的常量相似,常對(duì)象也是值不能被改變的量。C+語(yǔ)法如何確保常對(duì)象的值不會(huì)被改變呢?改變對(duì)象的數(shù)據(jù)成員的值有兩個(gè)途徑:一是在類(lèi)外通過(guò)對(duì)象名訪問(wèn)其公有數(shù)據(jù)成員,這時(shí)語(yǔ)法會(huì)限制不能再賦值;二是在類(lèi)的成員函數(shù)中改變數(shù)據(jù)成員的值,然而幾乎無(wú)法預(yù)知哪些成員函數(shù)會(huì)改變數(shù)據(jù)成員的值,對(duì)此語(yǔ)法規(guī)定不能通過(guò)常對(duì)象調(diào)用普通的成員函數(shù)。2.常引用使用const修飾符也可以說(shuō)明引用,被說(shuō)明的引用為常引用,被引用的對(duì)象不能被更新。常引用聲明格式如下:const & 在實(shí)際應(yīng)用中,常引用和常指針往往用來(lái)作函數(shù)的形參,這樣的參數(shù)稱(chēng)為常參數(shù)。例
19、6.6 常引用作函數(shù)形參示例。#includevoid display(const double & r);void main() double d(8.25); display(d);void display(const double & r)/常引用做形參,在函數(shù)中不能更新 r所引用的對(duì)象 coutrendl; 3.指向常量的指針和常指針常指針是指向固定、不能另指的指針。指向常量的指針是指指針?biāo)傅膶?duì)象為常對(duì)象。使用const修飾指針時(shí),由于const的位置不同,而含意不同。這里僅舉兩個(gè)例子,說(shuō)明它們的區(qū)別。例如,下面定義了一個(gè)指向字符串的常量指針:char * const prt1 =
20、stringprt1;其中,ptr1是一個(gè)常量指針。因此,下面賦值是非法的:ptr1 = stringprt2;而下面的賦值是合法的:*ptr1 = m;因?yàn)橹羔榩tr1所指向的變量是可以更新的,不可更新的是常量指針ptr1所指的方向(別的字符串)。又如,下面定義了一個(gè)指向字符串常量的指針:const char * ptr2 = stringprt1;其中,ptr2是一個(gè)指向字符串常量的指針。ptr2所指向的字符串不能更新的,而ptr2是可以更新的。ptr2是指向常量的指針。因此:*ptr2 = x;是非法的,而:ptr2 = stringptr2;是合法的。所以,在使用const修飾指針時(shí),
21、應(yīng)該注意const的位置。定義一個(gè)指向字符串的指針常量和定義一個(gè)指向字符串常量的指針時(shí),const修飾符的位置不同,前者const放在*和指針名之間,后者const放在類(lèi)型說(shuō)明符前。4.用const修飾的對(duì)象成員1)常成員函數(shù)使用const關(guān)鍵字進(jìn)行說(shuō)明的成員函數(shù),稱(chēng)為常成員函數(shù)。只有常成員函數(shù)才有資格操作常量或常對(duì)象,沒(méi)有使用const關(guān)鍵字說(shuō)明的成員函數(shù)不能用來(lái)操作常對(duì)象。通過(guò)常對(duì)象只能調(diào)用該對(duì)象的常成員函數(shù)。常成員函數(shù)說(shuō)明格式如下: () const;其中,const是加在函數(shù)說(shuō)明后面的類(lèi)型修飾符,它是函數(shù)類(lèi)型的一個(gè)組成部分,因此,在函數(shù)實(shí)現(xiàn)部分也要帶const關(guān)鍵字。下面通過(guò)一個(gè)具體的
22、例子說(shuō)明常成員函數(shù)的特征。例6.7 常成員函數(shù)示例。#include using namespace std;class Rpublic: R(int r1,int r2) R1=r1; R2=r2; void print(); void print() const; private: int R1, R2;void R:print() coutR1,R2endl;void R:print() const coutR1;R2endl;void main() R a(5,4); a.print(); /調(diào)用void print(); const R b(20, 52); b.print(); /
23、調(diào)用void print() const; 程序運(yùn)行結(jié)果: 5,4 20;52該程序的類(lèi)聲明了兩個(gè)成員函數(shù),其類(lèi)型是不同的(其實(shí)就是重載成員函數(shù))。在主程序中說(shuō)明了兩個(gè)對(duì)象a和b,其中對(duì)象b是常對(duì)象。通過(guò)對(duì)象a調(diào)用的是沒(méi)有用const修飾的成員函數(shù),而通過(guò)常對(duì)象b調(diào)用的是用const修飾的常成員函數(shù)。2)常數(shù)據(jù)成員使用const說(shuō)明的數(shù)據(jù)成員稱(chēng)為常數(shù)據(jù)成員。由于const類(lèi)型對(duì)象必須被初始化,并且不能更新,因此,在類(lèi)中說(shuō)明了const數(shù)據(jù)成員時(shí),只能通過(guò)成員初始化列表的方式來(lái)生成構(gòu)造函數(shù)以便對(duì)數(shù)據(jù)成員作初始化。例6.8 常成員函數(shù)示例。#include using namespace std;
24、class Apublic: A(int i); void print(); const int &r; /常數(shù)據(jù)成員引用private: const int a; /常數(shù)據(jù)成員 static const int b; /靜態(tài)常數(shù)據(jù)成員;const int A:b=10;/靜態(tài)常數(shù)據(jù)成員在類(lèi)外說(shuō)明和初始化A:A(int i):a(i),r(a)/只能通過(guò)成員初始化列表對(duì)常數(shù)據(jù)成員初始化void A:print() couta:b:rendl;void main() A a1(100), a2(0); a1.print(); a2.print();程序運(yùn)行結(jié)果:100:10:1000:10:0在
25、本例程序中,說(shuō)明了如下三個(gè)常類(lèi)型數(shù)據(jù)成員:const int & r;const int a;static const int b;其中,r是常int型數(shù)據(jù)成員的引用,a是常int型數(shù)據(jù)成員,b是靜態(tài)常int型數(shù)據(jù)成員。程序中對(duì)靜態(tài)數(shù)據(jù)成員b進(jìn)行初始化。值得注意的是構(gòu)造函數(shù)的格式按如下形式表示:A(int i):a(i),r(a)其中,冒號(hào)右邊是一個(gè)數(shù)據(jù)成員初始化列表,它包含兩個(gè)初始化項(xiàng),用逗號(hào)進(jìn)行了分隔,因?yàn)閿?shù)據(jù)成員a和r都是常類(lèi)型的,需要采用初始化格式。 主程序中,建立對(duì)象a1和a2并以100和0作為初值分別調(diào)用構(gòu)造函數(shù),通過(guò)構(gòu)造函數(shù)的初始化列表給對(duì)象的常數(shù)據(jù)成員賦初值。6.3.2靜態(tài)成員
26、創(chuàng)建一個(gè)對(duì)象,則該對(duì)象將擁有所有類(lèi)中的成員,如果某個(gè)數(shù)據(jù)對(duì)所有對(duì)象都一樣,則這個(gè)數(shù)據(jù)只要有一個(gè)拷貝,而不是每個(gè)對(duì)象都重復(fù)定義這個(gè)數(shù)據(jù),以避免內(nèi)存浪費(fèi)。簡(jiǎn)言之:一個(gè)數(shù)據(jù)拷貝,所有對(duì)象共享。引入靜態(tài)成員就可以很好解決類(lèi)對(duì)象之間的數(shù)據(jù)或函數(shù)的共享問(wèn)題。 例如,設(shè)有一個(gè)學(xué)生類(lèi):class student char *name, *num; int total; /學(xué)生總?cè)藬?shù) public: ; 應(yīng)用程序中聲明對(duì)象為: student a, b, c; 則對(duì)象a,b,c中都有數(shù)據(jù) total,而學(xué)生總數(shù)是一樣的,所以total 被重復(fù)定義了兩次。若把 total 聲明為靜態(tài)數(shù)據(jù)成員,就可避免這個(gè)問(wèn)題。1
27、.靜態(tài)數(shù)據(jù)成員將某數(shù)據(jù)成員聲明為靜態(tài)數(shù)據(jù)成員,只要在所要聲明的數(shù)據(jù)成員前加上關(guān)鍵字static即可。靜態(tài)數(shù)據(jù)成員可聲明為 private 或 public,它具有靜態(tài)生存期。 如,將學(xué)生類(lèi)中的學(xué)生總?cè)藬?shù)total聲明為靜態(tài)數(shù)據(jù)成員,學(xué)生類(lèi)聲明如下:class student char *name, *num; static int total; public: ; 例6.9 靜態(tài)數(shù)據(jù)成員應(yīng)用示例。#include #include using namespace std;class st_n char *name, *num; /學(xué)生姓名、學(xué)號(hào) static int total; /學(xué)生總?cè)藬?shù)
28、, 靜態(tài)數(shù)據(jù)成員public: st_n(char *, char *); st_n( ); void print( );int st_n:total=0; /靜態(tài)成員的初始化st_n:st_n(char *n1, char *n2) name=new charstrlen(n1)+1; num =new charstrlen(n2)+1; strcpy(name, n1); strcpy(num, n2); +total; /學(xué)生人數(shù)加1 void st_n:print( ) coutn name:name n num: num n total: total;st_n:st_n( ) del
29、ete name; delete num; -total; /學(xué)生人數(shù)減1 void main( ) st_n a(Wang , 000001); st_n b(Yang , 000002); st_n c(Tang , 000003); a.print( ); b.print( ); 程序運(yùn)行結(jié)果:name: Wang num: 000001 total: 3 name: Yang num: 000002 total: 3在本例程序中,a、b、c 三個(gè)對(duì)象的total都是3,即說(shuō)明靜態(tài)數(shù)據(jù)成員只有一個(gè)且為所有對(duì)象共享。total 被聲明為靜態(tài)數(shù)據(jù)成員,a、b、c三個(gè)對(duì)象共享該數(shù)據(jù)成員,即只有
30、一個(gè)拷貝。 使用靜態(tài)數(shù)據(jù)成員的正確方法是在類(lèi)內(nèi)對(duì)該數(shù)據(jù)成員作“引用性聲明”,在類(lèi)外定義和初始化,用(:)來(lái)指明所屬的類(lèi),具體定義格式為: 類(lèi)型名 類(lèi)名:數(shù)據(jù)名=初始值; 如: int st_n:total = 0;2.靜態(tài)成員函數(shù) 將某成員函數(shù)聲明為靜態(tài)成員函數(shù),只要在所要聲明的成員函數(shù)前加上關(guān)鍵字static即可。使用靜態(tài)成員函數(shù)的目的是對(duì)靜態(tài)數(shù)據(jù)成員進(jìn)行訪問(wèn)修改。 靜態(tài)成員函數(shù)有如下幾個(gè)特點(diǎn):1)靜態(tài)成員函數(shù)也是屬于整個(gè)類(lèi)。不論定義多少類(lèi)的對(duì)象,靜態(tài)成員函數(shù)也只有一個(gè)拷貝。2)靜態(tài)成員函數(shù)也是通過(guò)static來(lái)聲明。3)在程序中可以使用類(lèi)名或?qū)ο竺麃?lái)調(diào)用靜態(tài)成員函數(shù)。一般的成員函數(shù)則只能通
31、過(guò)對(duì)象名來(lái)調(diào)用。4)靜態(tài)成員函數(shù)只能訪問(wèn)屬于該類(lèi)的靜態(tài)數(shù)據(jù)成員或靜態(tài)成員函數(shù),而不能訪問(wèn)其他成員。例6.10 靜態(tài)函數(shù)應(yīng)用示例(接前例)。#include #include class st_n char *name,*num; /學(xué)生姓名、學(xué)號(hào)。 static int total; /學(xué)生總?cè)藬?shù), 靜態(tài)數(shù)據(jù)成員public: st_n(char *n1, char *n2); st_n( ); void print( ); static int getTotal( ); /靜態(tài)成員函數(shù);int st_n:total=0; /靜態(tài)數(shù)據(jù)成員的初始化st_n:st_n(char *n1, char
32、 *n2) name=new charstrlen(n1)+1; num =new charstrlen(n2)+1; strcpy(name, n1); strcpy(num, n2); +total; /學(xué)生人數(shù)加1 int st_n:getTotal() /定義靜態(tài)成員函數(shù)return total; /只能訪問(wèn)靜態(tài)數(shù)據(jù)成員void st_n:print() coutname:nameendl num: numendl;st_n:st_n () delete name; delete num; -total; /學(xué)生人數(shù)減1 void main( ) st_n a(Wang , 00000
33、1 ); st_n b(Yang , 000002 ); st_n c(Tang , 000003 ); a.print(); couttotal: a.getTotal()endl; b.print(); couttotal: st_n:getTotal()endl;程序運(yùn)行結(jié)果: name:Wang num: 000001 total: 3 name:Yang num: 000002 total: 3本例程序說(shuō)明:函數(shù)getTotal()被聲明為靜態(tài)成員函數(shù)。靜態(tài)成員函數(shù)可以通過(guò)對(duì)象調(diào)用, 也可以通過(guò)無(wú)對(duì)象調(diào)用(即類(lèi)名調(diào)用)。 如: a.getTotal( ); /由對(duì)象調(diào)用st_n:ge
34、tTotal( ); /由類(lèi)名調(diào)用靜態(tài)成員函數(shù)只能對(duì)靜態(tài)數(shù)據(jù)進(jìn)行操作, 不能對(duì)其它數(shù)據(jù)進(jìn)行操作。 如:int st_n:getTotal() /定義靜態(tài)成員函數(shù) return total; /在該函數(shù)體中只能訪問(wèn)靜態(tài)數(shù)據(jù)成員,不能訪問(wèn)其他非靜態(tài)成員6.4 友元前面講過(guò)類(lèi)具有封裝和數(shù)據(jù)隱藏的特性。只有類(lèi)的成員函數(shù)才能訪問(wèn)類(lèi)的私有成員,程序中其他函數(shù)是無(wú)法訪問(wèn)私有成員的。非成員函數(shù)可以訪問(wèn)類(lèi)中的公有成員,但是如果將數(shù)據(jù)成員都定義為公有的,這又會(huì)破壞隱藏的特性。另外,應(yīng)該看到在某些情況下,特別是在對(duì)某些成員函數(shù)多次調(diào)用時(shí),由于參數(shù)傳遞,類(lèi)型檢查和安全性檢查等都需要時(shí)間開(kāi)銷(xiāo),從而影響程序的執(zhí)行效率。為
35、解決上述問(wèn)題,C+提供了一種使用友元的解決方案。友元提供了不同類(lèi)或?qū)ο蟮某蓡T函數(shù)之間、類(lèi)的成員函數(shù)與一般函數(shù)之間進(jìn)行數(shù)據(jù)共享的機(jī)制。友元可以是一個(gè)函數(shù),該函數(shù)被稱(chēng)為友元函數(shù);友元也可以是一個(gè)類(lèi),該類(lèi)被子稱(chēng)為友元類(lèi)。下面分別講述這兩種友元。1.友元函數(shù)友元函數(shù)是在類(lèi)定義中由關(guān)鍵字friend修飾說(shuō)明的非成員函數(shù),在它的函數(shù)體中能夠通過(guò)對(duì)象名訪問(wèn) private 和 protected成員。友元函數(shù)的作用是可以增加靈活性,使程序員可以在封裝和快速性方面做合理選擇。在友元函數(shù)中,必須通過(guò)對(duì)象名才能對(duì)對(duì)象的私友或保護(hù)成員進(jìn)行訪問(wèn)。例6.11 友元函數(shù)使用示例。#include #include cla
36、ss Point /聲明類(lèi)Point public: /外部接口 Point(double xi, double yi) X=xi; Y=yi; double GetX() return X; double GetY() return Y; friend double Distance( Point& a, Point& b);/友元函數(shù)聲明 private: double X, Y; /私友數(shù)據(jù)成員;double Distance( Point& a, Point& b) /友元函數(shù)實(shí)現(xiàn) double dx=a.X-b.X; /通過(guò)對(duì)象訪問(wèn)私友成員 double dy=a.Y-b.Y; re
37、turn sqrt(dx*dx+dy*dy);int main() Point p1(3.0, 5.0), p2(4.0, 6.0); /聲明Point類(lèi)的對(duì)象double d=Distance(p1, p2); /計(jì)算兩點(diǎn)間的距離 coutThe distance is dendl; return 0; 在本例程序中,Point類(lèi)中聲明了一個(gè)友元函數(shù)Distance(),在它最左邊加friend關(guān)鍵字,標(biāo)識(shí)它不是成員函數(shù),而是友元函數(shù)。友元函數(shù)的定義方法與普通函數(shù)定義一樣,而不同于成員函數(shù)的定義,因?yàn)樗恍枰赋鏊鶎俚念?lèi)。但是,它可以引用類(lèi)的私有成員,函數(shù)體中a.x、a.y、b.x、b.y都
38、是類(lèi)的私有成員,它們是通過(guò)對(duì)象引用的。在調(diào)用友元函數(shù)時(shí),也是同普通函數(shù)一樣,不要像成員函數(shù)那樣調(diào)用。在主程序中,Distance(p1, p2)是友元函數(shù)的調(diào)用,它是直接調(diào)用,不需要通過(guò)對(duì)象來(lái)調(diào)用,它的參數(shù)是對(duì)象。2.友元類(lèi)友元除了可以是友元函數(shù)以外,還可以是友元類(lèi),即一個(gè)類(lèi)可作為另一個(gè)類(lèi)的友元。當(dāng)一個(gè)類(lèi)為另一個(gè)類(lèi)的友元時(shí),則該類(lèi)的所有成員都能訪問(wèn)對(duì)方類(lèi)的私有成員。友元類(lèi)的聲明方法是將友元類(lèi)名在另一個(gè)類(lèi)中用friend關(guān)鍵字進(jìn)行說(shuō)明,具體格式如下:friend class 類(lèi)名;其中:friend 和class 是關(guān)鍵字,類(lèi)名必須是程序中的一個(gè)已定義過(guò)的類(lèi)。如,將類(lèi)B聲明為類(lèi)A的友元類(lèi)的方法是
39、在A類(lèi)的聲明中加上說(shuō)明: friend class B;需要說(shuō)明的是,首先友元關(guān)系不具有對(duì)稱(chēng)性;此外,友元關(guān)系不具有傳遞性。如果類(lèi)B是類(lèi)A的友元類(lèi),類(lèi)C是類(lèi)B的友元類(lèi),這并不隱含類(lèi)C是類(lèi)A的友元類(lèi)。例6.12 友元類(lèi)使用示例。#include using namespace std;class A /聲明類(lèi)A private: friend class B; /聲明友員類(lèi)B char *name; int age; public: A( char *str, int i );A:A(char *str, int i) /A的構(gòu)造函數(shù)定義 name=str; /為類(lèi)A的成員賦值 age=i; c
40、lass B/聲明類(lèi)B,該類(lèi)中并沒(méi)有聲明A友員類(lèi) public: void show(A x); ;void B:show(A x) /B的show函數(shù)實(shí)現(xiàn) coutnnName:endl; coutnAge :x.ageendl;void main() A obj1(Li Xiangdong,30);/生成對(duì)象obj1 B obj2; /生成對(duì)象obj2 obj2.show(obj1); /調(diào)用obj2.show(),去訪問(wèn)obj1的成員在本例程序中,聲明了兩個(gè)類(lèi)A和B,在類(lèi)A中聲明了友員類(lèi)B。主程序中,用A和B各生成了一個(gè)對(duì)象,由于B是A的友元,這樣在類(lèi)B的成員函數(shù)show()
41、中就可以直接訪問(wèn)類(lèi)A中的私友成員了。 下面是友元的一些特性及使用注意事項(xiàng):友元是C+提供的一種破壞數(shù)據(jù)封裝和數(shù)據(jù)隱藏的機(jī)制。通過(guò)將一個(gè)模塊聲明為另一個(gè)模塊的友元,一個(gè)模塊能夠引用到另一個(gè)模塊中本是被隱藏的信息??梢允褂糜言瘮?shù)和友元類(lèi)。為了確保數(shù)據(jù)的完整性,以及數(shù)據(jù)封裝與隱藏的原則,建議盡量不使用或少使用友元。6.5 C+程序中的各類(lèi)文件1.C+程序中的文件類(lèi)型在前面章節(jié)中涉及到的C+源程序基本上由三個(gè)部分構(gòu)成:類(lèi)的聲明、類(lèi)的成員函數(shù)定義和main主函數(shù)。因?yàn)槔铀鉀Q的問(wèn)題規(guī)模較小,程序代碼較短,所以源程序的這三個(gè)部分都是以某個(gè)主文件名寫(xiě)到C+擴(kuò)展名為.cpp的單個(gè)文件中的。在實(shí)際問(wèn)題中,一
42、個(gè)復(fù)雜的C+程序通常是由多個(gè)文件組成的,這種結(jié)構(gòu)稱(chēng)為多文件結(jié)構(gòu)。在多文件結(jié)構(gòu)中,一個(gè)C+源程序一般至少可分為三個(gè)源文件,它們分別是:類(lèi)定義文件(.h文件)、類(lèi)實(shí)現(xiàn)文件(.cpp文件)、類(lèi)的使用文件(main函數(shù)所在的.cpp文件)。對(duì)于復(fù)雜的編程問(wèn)題,通常需要定義多個(gè)類(lèi),各個(gè)類(lèi)的定義和實(shí)現(xiàn)部分代碼一般都要單獨(dú)編寫(xiě),然后存入相應(yīng)的類(lèi)定義和類(lèi)實(shí)現(xiàn)文件中。在程序設(shè)計(jì)中,通常把類(lèi)定義的相關(guān)代碼存入擴(kuò)展名為h的頭文件(也可稱(chēng)作類(lèi)庫(kù)頭文件),把類(lèi)實(shí)現(xiàn)的相關(guān)代碼存入擴(kuò)展名為cpp的程序文件(也可稱(chēng)作類(lèi)庫(kù)的實(shí)現(xiàn)文件)。在多文件結(jié)構(gòu)中,C+程序的文件類(lèi)型一般可分為如下幾種:1)標(biāo)準(zhǔn)類(lèi)庫(kù)頭文件(擴(kuò)展名為.h)2)
43、標(biāo)準(zhǔn)函數(shù)頭文件(擴(kuò)展名為.h)3)自定義類(lèi)庫(kù)頭文件(擴(kuò)展名為.h)4)自定義函數(shù)頭文件(擴(kuò)展名為.h)5)用戶(hù)自定義類(lèi)庫(kù)的實(shí)現(xiàn)文件(擴(kuò)展名為.cpp)6)用戶(hù)自定義函數(shù)庫(kù)的實(shí)現(xiàn)文件(擴(kuò)展名為.cpp)7)主程序文件(main.cpp)8)C+程序工程文件(文件名與所使用的環(huán)境及編譯器有關(guān))在程序設(shè)計(jì)時(shí),通常使用#include包含命令把頭文件包含到相關(guān)的源文件中,前面4種頭文件的典型使用格式如下:#include #include #include”自定義類(lèi)庫(kù)頭文件”#include”自定義函數(shù)頭文件”2.利用工程來(lái)組合各類(lèi)文件采用多文件結(jié)構(gòu),可以對(duì)不同的文件進(jìn)行單獨(dú)編寫(xiě)、編譯,最后再連接生成
44、可執(zhí)行文件;同時(shí)可以充分利用類(lèi)的封裝特性,在程序修改和調(diào)試過(guò)程中只對(duì)其中某個(gè)類(lèi)的定義和實(shí)現(xiàn)進(jìn)行操作,而其余部分根本不需要改動(dòng)。對(duì)多文件結(jié)構(gòu)的組織和管理,在不同的環(huán)境下是由不同的方式來(lái)完成的。在Windows操作系統(tǒng)和DOS操作系統(tǒng)的C+編譯器中,一般是使用工程來(lái)組合各類(lèi)文件,并用工程對(duì)多文件進(jìn)行管理。例6.13 多文件結(jié)構(gòu)使用示例。/文件1:類(lèi)的聲明,stud.h#include #include class st_n char *name,*num; /學(xué)生姓名、學(xué)號(hào)。 static int total; /學(xué)生總?cè)藬?shù), 靜態(tài)數(shù)據(jù)成員public: st_n(char *n1, char *
45、n2); st_n( ); void print( ); static int getTotal( ); /靜態(tài)成員函數(shù);/文件2:類(lèi)的實(shí)現(xiàn),stud.cpp#includestud.hint st_n:total=0; /靜態(tài)數(shù)據(jù)成員的初始化st_n:st_n(char *n1, char *n2) name=new charstrlen(n1)+1; num =new charstrlen(n2)+1; strcpy(name, n1); strcpy(num, n2); +total; /學(xué)生人數(shù)加1 int st_n:getTotal() /定義靜態(tài)成員函數(shù)return total;
46、/只能訪問(wèn)靜態(tài)數(shù)據(jù)成員void st_n:print() coutname:nameendl num: numendl;st_n:st_n () delete name; delete num; -total; /學(xué)生人數(shù)減1 /文件3:主程序,fmain.cpp#includestud.hvoid main() st_n a(Wang ,000001 ); st_n b(Yang ,000002 ); st_n c(Tang ,000003 ); a.print(); couttotal: a.getTotal()endl; b.print(); couttotal: st_n:getTot
47、al()endl;從本例程序可以看出,這里僅對(duì)例6.10的程序按多文件結(jié)構(gòu)的組織方法進(jìn)行了改造,將程序按類(lèi)聲明、類(lèi)實(shí)現(xiàn)和主程序分成了stud.h、stud.cpp、fmain.cpp三個(gè)源文件。在本例程序的類(lèi)的實(shí)現(xiàn)文件和主程序文件中,使用了#include”stud.h”命令把自定義的頭文件包含進(jìn)來(lái)。若采用VC+6.0編譯器,可以使用把文件添加到工程的方式將本例的三個(gè)文件添加到工程中,并由工程對(duì)這些文件進(jìn)行統(tǒng)一管理。編譯器可以對(duì)stud.cpp、fmain.cpp兩個(gè)文件分別進(jìn)行編譯,并生成各自的目標(biāo)文件stud.obj和fmain.obj,然后再連接成可執(zhí)行文件.exe。若程序員只修改了類(lèi)的
48、成員函數(shù)的實(shí)現(xiàn)部分,只需重新編譯stud.cpp并連接即可,其余的文件幾乎用不著看。由此可見(jiàn),如果有一個(gè)語(yǔ)句很多、規(guī)模特大的程序,采用了多文件結(jié)構(gòu),不僅有助于開(kāi)發(fā)團(tuán)隊(duì)的協(xié)作分工,而且工作效率也會(huì)得到顯著的提高。6.6宏和編譯預(yù)處理在C+程序的源代碼中可以使用各種編譯指令,這些指令稱(chēng)為編譯預(yù)處理命令。C+提供的預(yù)處理命令主要有以下幾種:宏定義命令文件包含命令條件編譯命令這些命令在程序中都是以“#”來(lái)引導(dǎo),每條預(yù)處理命令必須單獨(dú)占用一行;它們不是C+的語(yǔ)句,因此在結(jié)尾沒(méi)有分號(hào)“;”。1.宏定義命令宏定義的一般形式為:#define 宏名 字符串 其中:define是宏替換的關(guān)鍵字,“宏名”是需要替換的標(biāo)識(shí)符,“字符串”是被指定用來(lái)替換的字符序列。如:#define PI 3.1415926說(shuō)明: 1)#define、宏名和字符串之間一定要有空格。2)宏名一般用大寫(xiě)字母表示,以區(qū)別于普通標(biāo)識(shí)符。3)宏被定義以后,一般不能再重新定義。但可以用#undef來(lái)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年室內(nèi)設(shè)計(jì)師年終工作總結(jié)參考樣本(四篇)
- 2024年和田二手房購(gòu)房合同(四篇)
- 2024年南京房屋租賃合同參考范文(三篇)
- 2024年圖書(shū)管理員個(gè)人工作計(jì)劃范本(二篇)
- 2024年小學(xué)營(yíng)養(yǎng)餐管理制度例文(三篇)
- 2024年幼兒園小班下學(xué)期工作計(jì)劃(五篇)
- 2024年大班上學(xué)期工作計(jì)劃樣本(二篇)
- 2024年奶茶店創(chuàng)業(yè)計(jì)劃書(shū)樣本(四篇)
- 2024年大型商場(chǎng)房屋出租合同(三篇)
- 2024年審計(jì)工作管理制度(二篇)
- 2024年部編新改版語(yǔ)文小學(xué)一年級(jí)上冊(cè)期中考試檢測(cè)題(有答案)
- GB/T 44109-2024信息技術(shù)大數(shù)據(jù)數(shù)據(jù)治理實(shí)施指南
- 《扣件式鋼管腳手架安全技術(shù)規(guī)范》JGJ130-2023
- 形物代與名物代練習(xí)題2頁(yè)
- 打拔機(jī)施工長(zhǎng)鋼護(hù)筒專(zhuān)項(xiàng)施工方案
- 畢業(yè)設(shè)計(jì)(論文)叉車(chē)液壓系統(tǒng)設(shè)計(jì)
- 研發(fā)項(xiàng)目立項(xiàng)管理流程總體思路.doc
- 榆林市第十二中學(xué)第二個(gè)五年發(fā)展規(guī)劃
- 廣西珍貴樹(shù)種發(fā)展規(guī)劃(2011~2020年)講解
- 盤(pán)縣紅果鎮(zhèn)上紙廠煤礦(技改)45萬(wàn)ta項(xiàng)目環(huán)境影響評(píng)價(jià)報(bào)告書(shū)
- 李居明大師趣談十二生肖
評(píng)論
0/150
提交評(píng)論