




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、關(guān)于函數(shù)和作用域第1頁,共52頁,2022年,5月20日,11點0分,星期四2.1 函數(shù)定義和調(diào)用C+的任何一個程序都可由一個主函數(shù)和若干個子函數(shù)組合而成。主函數(shù)可以調(diào)用子函數(shù),子函數(shù)還可以調(diào)用其他子函數(shù)。C+規(guī)定主函數(shù)名必須是main,而其他函數(shù)可以是庫函數(shù)或自定義函數(shù)。主函數(shù)main不僅是程序的入口函數(shù),而且與其他函數(shù)相比較還有許多使用上的限制。例如,它不能被其他函數(shù)調(diào)用,不能用inline和static來說明等。ANSI/ISO C+還規(guī)定主函數(shù)main的函數(shù)類型必須是int,以保證程序的移植性。庫函數(shù),又稱標(biāo)準(zhǔn)函數(shù),是ANSI/ISO C+編譯系統(tǒng)已經(jīng)預(yù)先定義好的函數(shù),程序設(shè)計時可根據(jù)
2、實際需要,直接使用這類函數(shù),而不必重新定義。調(diào)用時,必須在程序中包含相應(yīng)的頭文件,并指明使用名稱空間std。自定義函數(shù)是用戶根據(jù)程序的需要,將某一個功能相對獨立的程序定義成的一個函數(shù),或?qū)⒔鉀Q某個問題的算法用一個函數(shù)來組織。與變量的使用規(guī)則相同,在C+程序中一定要先說明和定義函數(shù),然后才能調(diào)用函數(shù)。C+中每一個函數(shù)的定義都是由4個部分組成的,即函數(shù)名、函數(shù)類型、形式參數(shù)表和函數(shù)體,其定義的格式如下: 2.1.1函數(shù)定義 ( ) 函數(shù)體第2頁,共52頁,2022年,5月20日,11點0分,星期四2.1.1 函數(shù)定義其中,函數(shù)名應(yīng)是一個合法有效的C+標(biāo)識符;函數(shù)頭的形式參數(shù)又簡稱為形參。參數(shù)表中的
3、每一個形參都是由形參的數(shù)據(jù)類型和形參名來構(gòu)成,形數(shù)個數(shù)可以是0,表示沒有形式參數(shù),但圓括號不能省略,也可以是1個或多個形參,但多個形參間要用逗號分隔。由花括號構(gòu)成的是函數(shù)的函數(shù)體部分,它可以有若干條語句,用于實現(xiàn)這個函數(shù)執(zhí)行的功能。根據(jù)上述定義格式,可以編寫一個函數(shù)sum,如圖2.1所示,注意它們的書寫規(guī)范。int sum(int x, int y)int z = x + y;return z;對齊函數(shù)頭函數(shù)體縮進(jìn)函數(shù)類型函數(shù)名形參圖2.1 定義一個函數(shù)sum第3頁,共52頁,2022年,5月20日,11點0分,星期四2.1.1 函數(shù)定義需要說明的是:(1) C/C+不允許在一個函數(shù)體中再定義
4、函數(shù),即禁止嵌套定義,但允許嵌套調(diào)用。(2) 函數(shù)體也可不含有任何語句,這樣的函數(shù)稱為空函數(shù),它僅為程序結(jié)構(gòu)而設(shè)定,本身沒有任何操作。(3) 函數(shù)類型決定了函數(shù)所需要的返回值類型,它可以是除數(shù)組類型之外的任何有效的C+數(shù)據(jù)類型,包括引用、指針等。一旦指定了函數(shù)類型,則須在函數(shù)體中通過return語句來指定函數(shù)的返回值,且返回值的類型應(yīng)與函數(shù)類型相同,若返回值的類型與函數(shù)類型不相同,則程序按類型自動轉(zhuǎn)換方式轉(zhuǎn)換成函數(shù)的類型或?qū)eturn后面的表達(dá)式進(jìn)行強(qiáng)制轉(zhuǎn)換。(4) 若函數(shù)類型為void時,則表示該函數(shù)沒有返回值。但仍然可以在函數(shù)體中使用return語句“return;”,此時可將“retu
5、rn;”語句理解為是函數(shù)體花括號“”的作用,當(dāng)流程遇到函數(shù)體的“”時,函數(shù)調(diào)用結(jié)束,控制權(quán)返回給主調(diào)函數(shù)。例如:void f1( int a)if (a 10)return;/ return;一旦執(zhí)行,后面的語句不再被執(zhí)行當(dāng)a10條件滿足時,“return;”語句將控制權(quán)返回給主調(diào)函數(shù)。第4頁,共52頁,2022年,5月20日,11點0分,星期四2.1.2 函數(shù)的調(diào)用和聲明1. 函數(shù)的實參和形參定義一個函數(shù)就是為了以后的調(diào)用。調(diào)用函數(shù)時,先寫函數(shù)名,然后緊跟括號,括號里是實際調(diào)用該函數(shù)時所給定的參數(shù),稱為實際參數(shù),簡稱實參,并與形參相對應(yīng)。要注意形參和實參的區(qū)別:(1) 從模塊概念來說,形參是
6、函數(shù)的接口,是存在于函數(shù)內(nèi)部的變量。而實參是存在于函數(shù)外部的變量。它們不是同一個實體,也就是說,形參變量和實參變量所對應(yīng)的內(nèi)存空間不是同一個內(nèi)存空間。(2) 按函數(shù)定義時所指定的形參類型,實參除變量外還可以是數(shù)值或表達(dá)式等,而形參只能是變量。(3) 形參在函數(shù)調(diào)用之前是不存在的,只有在發(fā)生函數(shù)調(diào)用時,函數(shù)中的形參才會被分配內(nèi)存空間,然后執(zhí)行函數(shù)體中的語句,而當(dāng)調(diào)用結(jié)束后,形參所占的內(nèi)存空間又會被釋放。2. 函數(shù)的調(diào)用函數(shù)調(diào)用的一般格式為:( )調(diào)用函數(shù)時要注意:實參與形參的個數(shù)應(yīng)相等,類型應(yīng)一致,且按順序?qū)?yīng),一一傳遞數(shù)據(jù)。例如,下面的示例用來輸出一個三角形的圖案。第5頁,共52頁,2022年
7、,5月20日,11點0分,星期四2.1.2 函數(shù)的調(diào)用和聲明 例Ex_Call 函數(shù)的調(diào)用#include using namespace std;void printline( char ch, int n )for (int i = 0 ; in ; i+)coutch;coutendl ;int main()int row = 5;for (int i = 0; irow; i+)printline(*, i+1);/ Areturn 0;程序運行的結(jié)果如下: 第6頁,共52頁,2022年,5月20日,11點0分,星期四2.1.2 函數(shù)的調(diào)用和聲明代碼中,main函數(shù)的for循環(huán)語句共調(diào)
8、用了5次printline函數(shù)(A句),每次調(diào)用時因?qū)崊+1值不斷改變,從而使函數(shù)printline打印出來的星號個數(shù)也隨之改變。printline函數(shù)由于沒有返回值,因此它作為一個語句來調(diào)用。事實上,對于有返回值的函數(shù)也可進(jìn)行這種方式的調(diào)用,只是此時不使用返回值,僅要求函數(shù)完成一定的操作。實際上,在C+中,一個函數(shù)的調(diào)用方式還有很多。例如,對于前面sum函數(shù)還可有下列調(diào)用方式:int b = 2 * sum(4, 5);/ Bint c = 1; c = sum(c, sum(c, 4);/ C其中,B語句把函數(shù)作為表達(dá)式的一部分,并將返回值參與運算,結(jié)果b = 18;C是將函數(shù)作為函數(shù)的
9、實參,等價于“c = sum(1, sum(1,4);”,執(zhí)行sum(1,4)后,等價于“c = sum(1,5) ;”,最后結(jié)果為c = 6。3. 函數(shù)的聲明由于前面函數(shù)printline的定義代碼是放在main函數(shù)中調(diào)用語句A之前,因而A語句執(zhí)行不會有問題。但若將函數(shù)printline的定義代碼放在調(diào)用語句A之后,即函數(shù)定義在后,而調(diào)用在前,就會產(chǎn)生“printline標(biāo)識符未定義”的編譯錯誤。此時必須在調(diào)用前進(jìn)行函數(shù)聲明。第7頁,共52頁,2022年,5月20日,11點0分,星期四2.1.2 函數(shù)的調(diào)用和聲明聲明一個函數(shù)按下列格式進(jìn)行: ( );可見,函數(shù)聲明的格式是在函數(shù)頭的后面加上分
10、號“;”。但要注意,函數(shù)聲明的內(nèi)容應(yīng)和函數(shù)的定義應(yīng)相同。例如,對于前面sum函數(shù)和最后一個printline函數(shù)可有如下聲明:int sum(int x, int y);void printline( char ch, int n );由于函數(shù)的聲明僅是對函數(shù)的原型進(jìn)行說明,即函數(shù)原型聲明,其聲明的形參變量名在聲明語句中并沒有任何語句操作它,因此這里的形參名和函數(shù)的定義時的形參名可以不同,且函數(shù)聲明時的形參名還可以省略,但函數(shù)名、函數(shù)類型、形參類型及個數(shù)應(yīng)與定義時相同。例如,下面幾種形式都是對sum函數(shù)原型的合法聲明:int sum(int a, int b); / 允許原型聲明時的形參名與定
11、義時不同int sum(int, int); / 省略全部形參名int sum(int a, int);/ 省略部分形參名int sum(int, int b);/ 省略部分形參名 不過,從程序的可讀性考慮,在聲明函數(shù)原型時,為每一個形參指定有意義的標(biāo)識符,并且和函數(shù)定義時的參數(shù)名相同,是一個非常好的習(xí)慣。第8頁,共52頁,2022年,5月20日,11點0分,星期四2.1.3 值傳遞在C+中,函數(shù)的參數(shù)傳遞有兩種方式,一是按值傳遞,二是地址傳遞或引用傳遞。這里先來說明按值傳遞的參數(shù)傳遞方法,地址傳遞或引用傳遞在以后來討論。當(dāng)函數(shù)的形參定義成一般變量時,如前面printline和sum函數(shù)的形參
12、都是一般變量,此時函數(shù)的參數(shù)傳遞就是按值傳遞方式,簡稱值傳遞,是指當(dāng)一個函數(shù)被調(diào)用時,C+根據(jù)實參和形參的對應(yīng)關(guān)系將實際參數(shù)的值一一傳遞給形參,供函數(shù)執(zhí)行時使用。值傳遞的特點是:(1) 若實參指定是變量,則傳遞的是實參變量的值而不是實參變量的地址。(2) 在執(zhí)行函數(shù)代碼時,由于對實參數(shù)據(jù)的操作最終是在形參的內(nèi)存空間中進(jìn)行,因此形參值的改變只是改變了形參的內(nèi)存空間存儲的值,而不會改變實參變量所對應(yīng)的內(nèi)存空間的值。也就是說,即使形參的值在函數(shù)中發(fā)生了變化,函數(shù)調(diào)用結(jié)束后,實參的值不會受到影響。例如:第9頁,共52頁,2022年,5月20日,11點0分,星期四2.1.3 值傳遞例Ex_SwapVal
13、ue 交換函數(shù)兩個參數(shù)的值。#include using namespace std;void swap(float x, float y);/ 函數(shù)原型說明int main()float a = 20, b = 40;couta = a, b = bn;swap(a, b);/ 函數(shù)調(diào)用couta = a, b = bn;return 0;void swap(float x, float y)/ 函數(shù)定義float temp;temp = x; x = y; y = temp;coutx = x, y = yn;第10頁,共52頁,2022年,5月20日,11點0分,星期四2.1.3 值傳遞
14、程序的運行結(jié)果為:可以看出,雖然函數(shù)swap中交換了兩個形參x和y的值,但交換的結(jié)果并不能改變實參的值,所以調(diào)用該函數(shù)后,變量a和b的值仍然為原來的值。 函數(shù)值傳遞方式的最大好處是保持函數(shù)的獨立性。在值傳遞方式下,函數(shù)只有通過指定函數(shù)類型并在函數(shù)體中使用return來返回某一類型的數(shù)值。第11頁,共52頁,2022年,5月20日,11點0分,星期四2.1.4 函數(shù)的默認(rèn)形參值在C+中,允許在函數(shù)的聲明或定義時給一個或多個參數(shù)指定默認(rèn)值。這樣在調(diào)用時,可以不給出實際參數(shù),而按指定的默認(rèn)值進(jìn)行工作。例如:void delay(int loops = 1000)/ 函數(shù)定義,1000為形參loops
15、的默認(rèn)值if ( 0 = loops) return;for (int i=0; iloops; i+);/ 空循環(huán),起延時作用這樣,當(dāng)有調(diào)用delay();/ 和delay(1000)等效時,程序就會自動將loops當(dāng)作成1000的默認(rèn)值來進(jìn)行處理。當(dāng)然,也可在函數(shù)調(diào)用時指定相應(yīng)的實際的參數(shù)值,例如:delay(2000);/ 形參loops的值為2000在設(shè)置函數(shù)的默認(rèn)形參值時要注意:(1) 當(dāng)函數(shù)既有原型聲明又有定義時,默認(rèn)參數(shù)只能在原型聲明中指定,而不能在函數(shù)定義中指定。例如:void delay(int loops);/ 函數(shù)原型聲明/ void delay(int loops =
16、1000)/ 錯誤:此時不能函數(shù)定義中指定默認(rèn)參數(shù)/ 第12頁,共52頁,2022年,5月20日,11點0分,星期四2.1.4 函數(shù)的默認(rèn)形參值(2) 當(dāng)一個函數(shù)中需要有多個默認(rèn)參數(shù)時,則形參分布中,默認(rèn)參數(shù)應(yīng)嚴(yán)格從右到左逐次定義和指定,中間不能跳開。例如:void display(int a, int b, int c = 3);/ 合法void display(int a, int b = 2, int c = 3);/ 合法void display(int a = 1, int b = 2, int c = 3);/ 合法:可以對所有的參數(shù)設(shè)置默認(rèn)值void display(int a,
17、 int b = 2, int c);/ 錯誤:默認(rèn)參數(shù)應(yīng)從最右邊開始void display(int a = 1, int b = 2, int c);/ 錯誤:默認(rèn)參數(shù)應(yīng)從最右邊開始void display(int a = 1, int b, int c = 3);/ 錯誤:多個默認(rèn)參數(shù)中間不能有非默認(rèn)參數(shù)(3) 當(dāng)帶有默認(rèn)參數(shù)的函數(shù)調(diào)用時,系統(tǒng)按從左到右的順序?qū)崊⑴c形參結(jié)合,當(dāng)實參的數(shù)目不足時,系統(tǒng)將按同樣的順序用聲明或定義中的默認(rèn)值來補(bǔ)齊所缺少的參數(shù)。第13頁,共52頁,2022年,5月20日,11點0分,星期四2.1.4 函數(shù)的默認(rèn)形參值例Ex_Default 在函數(shù)定義中設(shè)置多個
18、默認(rèn)參數(shù)#include using namespace std;void display(int a, int b = 2, int c = 3)/ 在函數(shù)定義中設(shè)置默認(rèn)參數(shù)couta = a, b = b, c = cn;int main()display(1);display(1, 5);display(1, 7, 9);return 0;程序的運行結(jié)果如下:第14頁,共52頁,2022年,5月20日,11點0分,星期四2.1.4 函數(shù)的默認(rèn)形參值(4) 由于對同一個函數(shù)的原型可作多次聲明,因此在函數(shù)聲明中指定多個默認(rèn)參數(shù)時,可用多條函數(shù)原型聲明語句來指定,但同一個參數(shù)的默認(rèn)值只能指定一
19、次。例如,例Ex_Default可改寫為:#include using namespace std;/ 下面2條函數(shù)說明語句等效于void display(int a, int b = 2, int c = 3);void display(int a, int b, int c=3);/ 指定c為默認(rèn)參數(shù)void display(int a, int b=2, int c);/ 指定b為默認(rèn)參數(shù)第15頁,共52頁,2022年,5月20日,11點0分,星期四 2.2 C+函數(shù)特性 函數(shù)重載(overloaded)是C+對C的擴(kuò)展,它允許多個同名的函數(shù)存在,但同名的各個函數(shù)的形參必須有區(qū)別:要么形
20、參的個數(shù)不同;要么形參的個數(shù)相同,但參數(shù)類型有所不同。 例Ex_OverLoad 編程求兩個或三個操作數(shù)之和程序的運行結(jié)果為: 從上面的例子可以看出:由于使用了函數(shù)的重載,因而不僅方便函數(shù)名的記憶,而且更主要的是完善了同一個函數(shù)的代碼功能,給調(diào)用帶來了許多方便。程序中各種形式的sum函數(shù)都稱為sum的重載函數(shù)。需要說明的是:(1) 重載函數(shù)必須具有不同的參數(shù)個數(shù)或不同的參數(shù)類型,若只有返回值的類型不同是不行的。例如:void fun(int a, int b);int fun(int a, int b);是錯誤的。因為如果有函數(shù)調(diào)用fun(2, 3)時,編譯器無法準(zhǔn)確地確定應(yīng)調(diào)用哪一個函數(shù)。(
21、2) 當(dāng)函數(shù)的重載帶有默認(rèn)參數(shù)時,也要應(yīng)該注意避免上述的二義性情況。例如:int fun(int a, int b = 0);int fun(int a);是錯誤的。因為如果有函數(shù)調(diào)用fun(2)時,編譯器也是無法準(zhǔn)確地確定應(yīng)調(diào)用哪一個函數(shù)。第16頁,共52頁,2022年,5月20日,11點0分,星期四2.2.2 函數(shù)嵌套調(diào)用C+允許在函數(shù)中再調(diào)用其他函數(shù),這種調(diào)用稱為函數(shù)的嵌套調(diào)用。例如,下面的示例是通過多個函數(shù)以及函數(shù)的嵌套調(diào)用來求解一元二次方程的根。 例Ex_Root 函數(shù)嵌套調(diào)用:求解一元二次方程的根本例main函數(shù)中調(diào)用了root函數(shù),root函數(shù)中又調(diào)用了sdelta和print函
22、數(shù),而sdelta函數(shù)還調(diào)用了cmath頭文件定義的庫函數(shù)sqrt(求平方根)和fabs(求浮點數(shù)的絕對值)。它們的調(diào)用關(guān)系如圖2.2所示。main函數(shù)root函數(shù)sdelta函數(shù)fabs庫函數(shù)print函數(shù)sqrt庫函數(shù)圖2.2 例Ex_Root中的各函數(shù)調(diào)用的關(guān)系第17頁,共52頁,2022年,5月20日,11點0分,星期四2.2.2 函數(shù)嵌套調(diào)用函數(shù)print用來輸出根的信息,當(dāng)n=0時,參數(shù)r1和r2無效,但調(diào)用該函數(shù)時還必須指定相應(yīng)的實際參數(shù),只是此時的實參值在函數(shù)執(zhí)行中不起作用。當(dāng)n=1時,只有參數(shù)r1有效,而當(dāng)n=2時,參數(shù)r1和r2才會都有效。函數(shù)sdelta用來計算一元二次方
23、程的系數(shù)a、b和c的b2-4ac的平方根。由于“d = b*b - 4.0 * a * c;”計算誤差,d值不一定剛好等于0.0,因此調(diào)用庫函數(shù)fabs求d的絕對值,并當(dāng)小于1.0e-10(1.0 x1010)時,將d值視為0.0,并返回0.0。當(dāng)d值大于0.0時,函數(shù)返回其平方根。當(dāng)d值小于0.0時,由于無法求出實平方根,因此作為程序技巧,函數(shù)返回-1.0。這樣當(dāng)在root函數(shù)中調(diào)用時,通過返回值的判斷來決定有無方程根。root函數(shù)用來求解一元二次方程的方程根并輸出,函數(shù)設(shè)計時要考慮:有無根、同根、不同根、系數(shù)a為0以及系數(shù)b為0等多種情況。程序運行的結(jié)果如下: 第18頁,共52頁,2022
24、年,5月20日,11點0分,星期四2.2.3 遞歸函數(shù)C+允許在調(diào)用一個函數(shù)的過程中出現(xiàn)直接地或間接地調(diào)用函數(shù)本身,這種情況稱為函數(shù)的遞歸調(diào)用。遞歸(Recursion)是一種常用的程序方法(算法),相應(yīng)的函數(shù)稱為遞歸函數(shù)。例如,用遞歸函數(shù)編程求n的階乘n!。n!=n*(n-1)*(n-2)*.*2*1。它也可用下式表示:由于n!和(n-1)!都是同一個問題的求解,因此可將n!用遞歸函數(shù)long factorial(int n)來描述,程序代碼如下: 例Ex_Factorial 編程求n的階乘n!#include using namespace std;long factorial(int n
25、);int main()coutfactorial(4)0時第19頁,共52頁,2022年,5月20日,11點0分,星期四2.2.3 遞歸函數(shù)在函數(shù)factorial中,當(dāng)n不等于0時,又調(diào)用了該函數(shù)本身。下面來分析此函數(shù)的執(zhí)行過程:(1) 因n = 4,不等于0,故執(zhí)行“result = 4*factorial(3);”,函數(shù)返回的值為4*factorial(3),即factorial(4) = 4*factorial(3);(2) 調(diào)用“factorial(3);”, n = 3不等于0,執(zhí)行“result=3*factorial(2);”,函數(shù)返回的值為3*factorial(2) ,即
26、factorial(3) =3*factorial(2);(3) 調(diào)用“factorial(2);”, n = 2不等于0,執(zhí)行“result=2*factorial(1);”, 函數(shù)返回的值為2*factorial(1) ,即factorial(2) =2*factorial(1);(4) 調(diào)用“factorial(1);”,n = 1不等于0,執(zhí)行“result=1*factorial(0);”, 函數(shù)返回的值為1*factorial(0) ,即factorial(1) =1*factorial(0);(5) 調(diào)用“factorial(0);”,n等于0,結(jié)果函數(shù)返回的值為1。上述過程是根
27、據(jù)程序運行過程進(jìn)行推算的,這個過程稱為“遞推”過程。函數(shù)的遞歸調(diào)用在遞推過程后還進(jìn)行另一稱為“回歸”的過程,它是按“遞推”的逆過程,逐一求值回歸,一直到達(dá)遞推的開始處。因此,當(dāng)factorial(0) = 1后,factorial(1) = 1*1,factorial(2) = 2*1*1,factorial(3) = 3*2*1*1,factorial(4) = 4*3*2*1*1,結(jié)果為4!,值為24。第20頁,共52頁,2022年,5月20日,11點0分,星期四2.2.3 遞歸函數(shù)以上的例子可以看出,函數(shù)的遞歸調(diào)用能使程序精巧、高效。但要注意,遞歸函數(shù)中必須要有結(jié)束遞歸過程的條件,否則遞
28、歸會無限制地進(jìn)行下去。例如,在上述代碼中,if (n=0) result=1;就是結(jié)束遞歸過程的條件,若函數(shù)factorial變?yōu)椋簂ong factorial(int n)long result=0;result = n*factorial(n-1);return result;則遞歸會無限制地進(jìn)行下去,此程序?qū)⒆兊煤翢o用途。需要說明的是:雖然遞歸調(diào)用編寫的程序簡潔清晰,但每次調(diào)用函數(shù)時,都需要分配內(nèi)存來保存現(xiàn)場和返回地址,內(nèi)存空間開銷很大,有時會引起棧內(nèi)存溢出。第21頁,共52頁,2022年,5月20日,11點0分,星期四2.2.4 內(nèi)聯(lián)函數(shù)在程序的執(zhí)行過程中,調(diào)用函數(shù)時首先需要保存主調(diào)函
29、數(shù)的現(xiàn)場和返回地址,然后程序轉(zhuǎn)移到被調(diào)函數(shù)的起始地址繼續(xù)執(zhí)行。被調(diào)函數(shù)執(zhí)行結(jié)束后,先恢復(fù)主調(diào)函數(shù)的現(xiàn)場,取出返回地址并將返回值賦給函數(shù)調(diào)用本身,最后在返回地址處開始繼續(xù)執(zhí)行。當(dāng)函數(shù)體比較小且執(zhí)行的功能比較簡單時,這種函數(shù)調(diào)用方式的系統(tǒng)開銷相對較大。為了解決這一問題,C+引入了內(nèi)聯(lián)函數(shù)的概念,它把函數(shù)體的代碼直接插入到調(diào)用處,將調(diào)用函數(shù)的方式改為順序執(zhí)行直接插入的程序代碼,這樣可以減少程序的執(zhí)行時間,但同時增加了代碼的實際長度。內(nèi)聯(lián)函數(shù)的使用方法與一般函數(shù)相同,只是在內(nèi)聯(lián)函數(shù)定義時,需在函數(shù)的類型前面加上inline關(guān)鍵字。例如: 例Ex_Inline 用內(nèi)聯(lián)函數(shù)實現(xiàn)求兩個實數(shù)的最大值#incl
30、ude using namespace std;inline float fmax(float x, float y)return xy?x:y;int main()float a;a = fmax(5, 10);/ Acout最大的數(shù)為:a10 ? 5 : 10;程序的運行結(jié)果如下: 在使用內(nèi)聯(lián)函數(shù)時,還需要注意的是:(1) 內(nèi)聯(lián)函數(shù)也要遵循定義在前,調(diào)用在后的原則。形參與實參之間的關(guān)系與一般函數(shù)相同。(2) 關(guān)鍵字inline必須放在函數(shù)定義體前才是內(nèi)聯(lián)函數(shù),僅在函數(shù)聲明時使用inline而不在定義體前使用,不能定義內(nèi)聯(lián)函數(shù)。(3) 在C+中,需要定義成的內(nèi)聯(lián)函數(shù)不能含有循環(huán)、switch
31、和復(fù)雜嵌套的if語句。(4) 遞歸函數(shù)不能被用來做內(nèi)聯(lián)函數(shù)。(5) 編譯器是否將用戶定義成的內(nèi)聯(lián)函數(shù)作為真正的內(nèi)聯(lián)函數(shù)處理,由編譯器自行決定。總之,內(nèi)聯(lián)函數(shù)一般是比較小的、經(jīng)常被調(diào)用的、大多可在一行寫完的函數(shù),并常用來代替以后要討論的帶參數(shù)的宏定義。第23頁,共52頁,2022年,5月20日,11點0分,星期四2.3 作用域和存儲類型作用域又稱作用范圍,是指程序中標(biāo)識符(變量名、函數(shù)名、數(shù)組名、類名、對象名等)的有效范圍。一個標(biāo)識符是否可以被引用,稱之為標(biāo)識符的可見性。在一個C+程序項目中,一個標(biāo)識符只能在聲明或定義它的范圍內(nèi)可見,在此之外是不可見的。根據(jù)標(biāo)識符的作用范圍,可將其作用域分為5種
32、:函數(shù)原型作用域、函數(shù)作用域、塊作用域、類作用域和文件作用域。其中,類作用域?qū)⒃谝院蠼榻B,這里介紹其他幾種。1. 函數(shù)原型作用域函數(shù)原型作用域指的是在聲明函數(shù)原型所指定的參數(shù)標(biāo)識符的作用范圍。這個作用范圍是在函數(shù)原型聲明中的左、右圓括號之間。正因為如此,在函數(shù)原型中聲明的標(biāo)識符可以與函數(shù)定義中說明的標(biāo)識符名稱不同。由于所聲明的標(biāo)識符與該函數(shù)的定義及調(diào)用無關(guān),所以可以在函數(shù)原型聲明中只作參數(shù)的類型聲明,而省略參數(shù)名。例如:double max(double x, double y);和double max(double, double);是等價的。2. 函數(shù)作用域具有函數(shù)作用域的標(biāo)識符在聲明它的
33、函數(shù)內(nèi)可見,但在此函數(shù)之外是不可見的。在C+語言中,只有g(shù)oto語句使用的標(biāo)號是惟一具有函數(shù)作用域的標(biāo)識符。2.3.1作用域第24頁,共52頁,2022年,5月20日,11點0分,星期四2.3.1 作用域這里的塊就是由“”和“”組成的塊語句(復(fù)合語句)。在塊中聲明的標(biāo)識符,其作用域從聲明處開始,一直到結(jié)束塊的花括號為止。塊作用域也稱作局部作用域,具有塊作用域的變量是局部變量。例如:void fun(void)/ 在形參中指定void,表示沒有形參,void可不要a的作用域b的作用域int a;/ a的作用域起始處cina;if (a0) a = -a;int b;/ b的作用域起始處/ b的作
34、用域終止處 / a的作用域終止處代碼中,聲明的局部變量a和b處在不同的塊中。其中變量a是在fun函數(shù)的函數(shù)體塊中,因此在函數(shù)體這個范圍內(nèi),該變量是可見的。而b是在if語句塊中聲明的,故它的作用域是從聲明處開始到if語句結(jié)束處終止。a的作用域b的作用域第25頁,共52頁,2022年,5月20日,11點0分,星期四2.3.1 作用域需要說明的是:當(dāng)標(biāo)識符的作用域完全相同時,不允許出現(xiàn)相同的標(biāo)識符名。而當(dāng)標(biāo)識符具有不同的作用域時,卻允許標(biāo)識符同名。例如:void fun(void)塊A塊B/ 塊A開始int i;/ 塊B開始int i;i = 100;/ 塊B結(jié)束/ 塊A結(jié)束代碼中,在A和B塊中都聲
35、明了變量i,這是允許的,因為塊A和塊B不是同一個作用域。但同時出現(xiàn)另外一個問題,語句“i = 100;”中的i是使用A塊中的變量i還是使用B中的變量i?C+規(guī)定在這種作用域嵌套的情況下,如果內(nèi)層(塊B)和外層(塊A)作用域聲明了同名的標(biāo)識符,那么在外層作用域中聲明的標(biāo)識符對于該內(nèi)層作用域是不可見的。也就是說,在塊B聲明的變量i與塊A聲明的變量i無關(guān),當(dāng)塊B中的i=100時,不會影響塊A中變量i的值。塊A塊B第26頁,共52頁,2022年,5月20日,11點0分,星期四2.3.1 作用域4. 文件作用域在所有函數(shù)外定義的標(biāo)識符稱為全局標(biāo)識符。全局標(biāo)識符的作用域是文件作用域,它從聲明之處開始,直到
36、文件結(jié)束一直是可見的。具有文件作用域的變量和常量稱為全局變量和全局常量,例如:const float PI = 3.14;/ 全局常量PI,其作用域從此開始到文件結(jié)束int a;/ 全局變量a,其作用域從此開始到文件結(jié)束void main( ) / void funA(int x) / 其中,全局常量PI和全局變量a的作用域是文件作用域。標(biāo)識符的文件作用域一般還有以下幾種情況:第27頁,共52頁,2022年,5月20日,11點0分,星期四2.3.1 作用域(1) 若函數(shù)定義在后,調(diào)用在前,必須進(jìn)行函數(shù)原型聲明。若函數(shù)定義在前,調(diào)用在后,函數(shù)定義包含了函數(shù)的原型聲明。一旦聲明了函數(shù)原型,函數(shù)標(biāo)識
37、符的作用域是從定義開始到源程序文件結(jié)束。例如:void funA(int x ); / 函數(shù)funA的作用域從此開始到文件結(jié)束void funB( ) / 函數(shù)funA的作用域從此開始到文件結(jié)束/ void main( ) / void funA(int x) / (2) 對于在頭文件中定義的標(biāo)識符,當(dāng)它們被預(yù)編譯時,會將頭文件的內(nèi)容在源文件的相應(yīng)位置展開,所以在頭文件中定義的標(biāo)識符的作用域可以看成從#include該頭文件開始的位置到源程序文件結(jié)束。例如,以前示例中頭文件iostream的std:cin和std:cout的作用域是從#include預(yù)處理指令開始一直到源程序文件結(jié)束。 注意,
38、若使用ANSI/ISO C+新文件格式的包含,則cin和cout的作用域是從using語句開始一直到源程序文件結(jié)束。第28頁,共52頁,2022年,5月20日,11點0分,星期四2.3.2 域運算符在C+中,若在塊作用域內(nèi)使用與局部標(biāo)識符同名的塊外標(biāo)識符時,則須使用域運算符“:”來引用,且該標(biāo)識符一定要是全局標(biāo)識符,即它具有文件作用域。例如: 例Ex_Process 在塊作用內(nèi)引用文件作用域的同名變量#include using namespace std;int i = 10;/ Aint main()int i = 20;/ Bint i = 5;/ Cint j;:i = :i + 4;
39、/ :i是引用A定義的變量i,不是B中的ij = :i + i;/ 這里不加:的i是C中定義的變量cout:i = :i, j = jn;cout:i = :i, i = in;/ 這里不加:的i是B中定義的變量return 0; 程序的運行結(jié)果為:需要說明的是,域運算符“:”往往還用于指定引用對象所屬的類、名稱空間等。第29頁,共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型存儲類型是針對變量而言的,它規(guī)定了變量的生存期。無論是全局變量還是局部變量,編譯系統(tǒng)往往根據(jù)其存儲方式定義、分配和釋放相應(yīng)的內(nèi)存空間。變量的存儲類型反映了變量在哪開辟內(nèi)存空間以及占用內(nèi)存空間的有效
40、期限。在C+中,變量有4種存儲類型:自動類型、靜態(tài)類型、寄存器類型和外部類型,這些存儲類型是在變量定義時來指定的,其一般格式如下: ; 1. 自動類型和寄存器類型一般說來,用自動存儲類型聲明的變量都是限制在某個程序范圍內(nèi)使用,即為局部變量。從系統(tǒng)角度來說,自動存儲類型變量是采用動態(tài)分配方式在棧區(qū)中來分配內(nèi)存空間。因此,當(dāng)程序執(zhí)行到超出該變量的作用域時,就釋放它所占用的內(nèi)存空間,其值也隨之消失了。在C+語言中,聲明一個自動存儲類型的變量是在變量類型前加上關(guān)鍵字auto,例如:autoint i;若自動存儲類型的變量是在函數(shù)內(nèi)或語句塊中聲明的,則可省略關(guān)鍵字auto,例如:void fun()in
41、t i;/ 省略auto/ 第30頁,共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型使用關(guān)鍵字register聲明寄存器類型的變量的目的是將所聲明的變量放入寄存器內(nèi),從而加快程序的運行速度。例如:register int i;/ 聲明寄存器類型變量但有時,在使用register聲明時,若系統(tǒng)寄存器已經(jīng)被其他數(shù)據(jù)占據(jù)時,寄存器類型的變量就會自動當(dāng)作auto變量。2. 靜態(tài)類型從變量的生存期來說,一個變量的存儲空間可以是永久的,即在程序運行期間該變量一直存在,如全局變量;也可以是臨時的,如局部變量,當(dāng)流程執(zhí)行到它的說明語句時,系統(tǒng)為其在棧區(qū)中動態(tài)分配一個臨時的內(nèi)存空間,并
42、在它的作用域中有效,一旦流程超出該變量的作用域時,就釋放它所占用的內(nèi)存空間,其值也隨之消失。但是,若在聲明局部變量類型前面加上關(guān)鍵字static,則將其定義成了一個靜態(tài)類型的變量。這樣的變量雖具有局部變量的作用域,但由于它是用靜態(tài)分配方式在靜態(tài)數(shù)據(jù)區(qū)中來分配內(nèi)存空間。因此,在這種方式下,只要程序還在繼續(xù)執(zhí)行,靜態(tài)類型變量的值就一直有效,不會隨它所在的函數(shù)或語句塊的結(jié)束而消失。簡單地說,靜態(tài)類型的局部變量雖具有局部變量的作用域,但卻有全局變量的生存期。 值得注意的是,如需定義一個很大的數(shù)組時,則應(yīng)將數(shù)組定義成全局?jǐn)?shù)組或?qū)?shù)組的存儲類型定義成static,而不應(yīng)定義成自動存儲類型或局部數(shù)組,因為靜
43、態(tài)數(shù)據(jù)區(qū)的內(nèi)存要比棧區(qū)內(nèi)存大許多。例如:static intarray5000;/ 指定靜態(tài)存儲類型第31頁,共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型需要說明的是,靜態(tài)類型的局部變量只在第一次執(zhí)行時進(jìn)行初始化,正因為如此,在聲明靜態(tài)類型變量時一定要指定其初值,若沒有指定,編譯器還會將其初值置為0。例如:例Ex_Static 使用靜態(tài)類型的局部變量#include using namespace std;void count()int i = 0;static int j = 0; / 靜態(tài)類型i+;j+;couti = i, j = jn;int main()c
44、ount();count();return 0;第32頁,共52頁,2022年,5月20日,11點0分,星期四 2.3.3 存儲類型程序中,當(dāng)?shù)?次調(diào)用函數(shù)count時,由于變量j是靜態(tài)類型,因此其初值設(shè)為0后不再進(jìn)行初始化,執(zhí)行j+后,j值為1,并一直有效。第2次調(diào)用函數(shù)count時,由于j已分配內(nèi)存且進(jìn)行過初始化,因此語句“static int j = 0;”被跳過,執(zhí)行j+后,j值為2。故程序運行結(jié)果為: 事實上,在程序中聲明的全局變量總是靜態(tài)存儲類型,若在全局變量前加上static,使該變量只在這個源程序文件內(nèi)使用,稱之為全局靜態(tài)變量或靜態(tài)全局變量。若一個程序由一個文件組成,在聲明全局
45、變量時,有無static并沒有區(qū)別,但若多個文件組成一個程序時,加與不加static,其作用完全不同。例如: 第33頁,共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型 例Ex_StaticScope 使用靜態(tài)類型的全部變量(1) 用Visual C+中的AppWizard創(chuàng)建一個控制臺應(yīng)用程序Ex_StaticScope,在創(chuàng)建過程中選擇項目類型為“一個簡單的程序(A simple application)”。(2) 在Ex_StaticScope.cpp文件中添加下列代碼:#include stdafx.h#include using namespace std;i
46、nt n;void f();/ 先作函數(shù)原型聲明,函數(shù)定義在另一個文件中int main()n = 20;coutn = nn;f();return 0;第34頁,共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型代碼中,#include stdafx.h語句是Visual C+應(yīng)用程序向?qū)ё詣犹砑拥?。stdafx.h是每個Visual C+應(yīng)用程序所必有的預(yù)編譯頭文件,程序所用到的Visual C+頭文件包含語句一般均應(yīng)添加到這個文件中。函數(shù)f先在該文件中作函數(shù)的原型聲明,函數(shù)的定義在另一個文件中,這是Visual C+所允許的。選擇“文件”“新建”菜單命令,默認(rèn)時會自
47、動將“新建”對話框切換到“文件”頁面,選中“C+ Source File”文件類型,在文件編輯框中輸入Ex_StaticScope_1.cpp,如圖2.3所示。單擊確定按鈕,在Ex_StaticScope_1.cpp中添加下列代碼:#include stdafx.h#include using namespace std;static int n;/ 默認(rèn)初值為0void f()/ 函數(shù)定義n+;/ 這里的n是本文件定義的靜態(tài)類型變量coutn = nn; 第35頁,共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型圖2.3 向項目中添加C+文件項目Ex_StaticSc
48、ope運行后,其結(jié)果如下: 可見,函數(shù)f輸出1而不是21,表明Ex_StaticScope.cpp中的全局變量n和Ex_Static- Scope_1.cpp中的靜態(tài)全局變量n是互不相干的。因此,靜態(tài)全局變量對組成該程序的其他源文件是無效的,它能很好地解決在程序多文件組織中全局變量的重名問題。同靜態(tài)全局變量相類似,靜態(tài)函數(shù)也是在某個函數(shù)聲明前加上static,它的目的也是使該函數(shù)只在聲明的源文件中使用,對于其他源文件則無效。 第36頁,共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型3. 外部類型使用關(guān)鍵字extern聲明的變量稱為外部變量,一般是指定義在本程序外部的變
49、量。當(dāng)某個變量被聲明成外部變量時,不必再次為它分配內(nèi)存就可以在本程序中引用這個變量。在C+中,只有在兩種情況下需要使用外部變量。第一種情況:在同一個源文件中,若定義的變量使用在前,聲明在后,這時在使用前要聲明為外部變量。例如: 例Ex_Extern1 同一個源文件中的外部變量使用#include using namespace std;extern int a;/ 聲明外部變量a,/ 若沒有此語句,函數(shù)count中的語句將出錯void count()a+;coutan;int a = 10;/ 外部變量a的實際聲明處int main()count();coutan;return 0;第37頁,
50、共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型運行結(jié)果為: 第二種情況:當(dāng)由多個文件組成一個完整的程序時,在一個源程序文件中定義的變量要被其他若干個源文件引用時,引用的文件中要用extern對該變量作外部聲明。例如,創(chuàng)建一個Ex_Extern2項目,包含兩個源文件,一個是Ex_Extern2.cpp,另一個是Ex_Extern2_1.cpp。 例Ex_ Extern2 不在同一個源文件中的外部變量使用 Ex_Extern2.cpp文件內(nèi)容#include stdafx.h#include using namespace std;int n;void f();int m
51、ain()n = 20;coutn = nn;f();return 0; 第38頁,共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型 Ex_Extern2_1.cpp文件內(nèi)容#include stdafx.h#include using namespace std;extern int n;/ 外部變量聲明,它在另一個文件中定義void f()n+;coutn = nn;項目Ex_StaticScope經(jīng)運行后,結(jié)果如下: 需要注意的是:(1) 可以對同一個變量進(jìn)行多次extern的聲明。若在聲明時,給一個外部變量賦初值,則編譯器認(rèn)為是一個具體的變量定義,而不是一個外部
52、變量的聲明,此時要注意同名標(biāo)識符的重復(fù)定義。例如:extern int n = 1;/ 變量定義int n;/ 錯誤:變量n重復(fù)定義(2) 雖然外部變量對不同源文件中或函數(shù)之間的數(shù)據(jù)傳遞特別有用。但也應(yīng)該看到,這種能被許多函數(shù)共享的外部變量,其數(shù)值的任何一次改變,都將影響到所有引用此變量的函數(shù)的執(zhí)行結(jié)果,其危險性是顯然的。 第39頁,共52頁,2022年,5月20日,11點0分,星期四2.4 名稱空間在C+中,定義一個名稱空間的格式如下:2.4.1 名稱空間的定義namespace 標(biāo)識符成員;體其中,namespace是C+關(guān)鍵字,標(biāo)識符用作名稱空間的名稱,屬于該名稱空間體中的變量、函數(shù)、結(jié)
53、構(gòu)、枚舉、聯(lián)合以及以后要討論的類等都可以認(rèn)為是該名稱空間的成員。需要說明的是:第40頁,共52頁,2022年,5月20日,11點0分,星期四2.4.1 名稱空間的定義(1) 同一個文件中,可以允許定義多個名稱空間。一旦定義名稱空間后,標(biāo)識符就標(biāo)識名稱空間體的那個區(qū)域。例如:using namespace std;namespace DING1char name = this is in DING1 region!;void showname( void )coutnameendl;namespace DING2char name = this is in DING2 region!;void
54、showname( void )coutnameendl;盡管名稱空間DIN1和DING2中定義的成員名都相同,但它們由于分屬不同的名稱區(qū)域,因而是合法的。此后,在引用各自的成員時就可使用域作用符來指定DIN1或DING2來標(biāo)識各自所在的名稱區(qū)域。第41頁,共52頁,2022年,5月20日,11點0分,星期四2.4.1 名稱空間的定義(2) 名稱空間中的函數(shù)、類等可稱為成員函數(shù)和成員類。成員函數(shù)的原型必須在名稱空間體中聲明,而此時的函數(shù)定義稱為函數(shù)的實現(xiàn),可以在體內(nèi)完成,也可在體外完成。例如,前面名稱空間DING1和DING2的成員函數(shù)showname的聲明和定義都是在體內(nèi)一起完成的,若將成員函數(shù)showname的實現(xiàn)放在體外完成,則必須用域作用符“:”指明其所屬名稱空間。例如:using namespace std;namespace DING1char name = this is in DING1 region!;void shown
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五版國際貿(mào)易中電子合同書的法律問題
- 投資公司的反擔(dān)保保證合同書二零二五年
- 銷售提成合同書范例
- 大學(xué)生職業(yè)規(guī)劃大賽《數(shù)字媒體藝術(shù)專業(yè)》生涯發(fā)展展示
- 2025關(guān)于建筑給排水安裝的勞務(wù)承包合同
- 2025合作伙伴與企業(yè)的租賃合同格式
- 2025年建筑工程公司合同風(fēng)險防范與管理的探討(格式)
- 2025年簽訂房屋買賣合同時應(yīng)注意哪些事項
- 《2025項目管理分包合同》
- 2025簡易租賃住房合同
- 2024年5月廣東省公務(wù)員考試公安聯(lián)考結(jié)構(gòu)化面試真題試題試卷答案解析
- 2025-2030中國醫(yī)療領(lǐng)域的射頻識別設(shè)備(RFID)行業(yè)市場發(fā)展趨勢與前景展望戰(zhàn)略研究報告
- 2025至2030中國車載OLED屏市場未來前景展望及運行態(tài)勢剖析報告
- 2024-2025學(xué)年八年級下學(xué)期道德與法治期中模擬試卷(二)(統(tǒng)編版含答案解析)
- 2025-2030中國生物醫(yī)藥行業(yè)市場深度調(diào)研及發(fā)展趨勢與投資前景預(yù)測研究報告
- 貿(mào)易公司員工管理制度
- 專利代理師高頻題庫新版2025
- T-GXAS 421-2022 成人急性中毒洗胃操作技術(shù)規(guī)范
- 中國風(fēng)武術(shù)太極拳主題PPT模板
- 蘇州園林的藝術(shù)特色之拙政園講解
- Y-Y2系列電機(jī)繞組標(biāo)準(zhǔn)數(shù)據(jù)匯總
評論
0/150
提交評論