




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、關于函數(shù)和作用域第1頁,共52頁,2022年,5月20日,11點0分,星期四2.1 函數(shù)定義和調用C+的任何一個程序都可由一個主函數(shù)和若干個子函數(shù)組合而成。主函數(shù)可以調用子函數(shù),子函數(shù)還可以調用其他子函數(shù)。C+規(guī)定主函數(shù)名必須是main,而其他函數(shù)可以是庫函數(shù)或自定義函數(shù)。主函數(shù)main不僅是程序的入口函數(shù),而且與其他函數(shù)相比較還有許多使用上的限制。例如,它不能被其他函數(shù)調用,不能用inline和static來說明等。ANSI/ISO C+還規(guī)定主函數(shù)main的函數(shù)類型必須是int,以保證程序的移植性。庫函數(shù),又稱標準函數(shù),是ANSI/ISO C+編譯系統(tǒng)已經(jīng)預先定義好的函數(shù),程序設計時可根據(jù)
2、實際需要,直接使用這類函數(shù),而不必重新定義。調用時,必須在程序中包含相應的頭文件,并指明使用名稱空間std。自定義函數(shù)是用戶根據(jù)程序的需要,將某一個功能相對獨立的程序定義成的一個函數(shù),或將解決某個問題的算法用一個函數(shù)來組織。與變量的使用規(guī)則相同,在C+程序中一定要先說明和定義函數(shù),然后才能調用函數(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ù)名應是一個合法有效的C+標識符;函數(shù)頭的形式參數(shù)又簡稱為形參。參數(shù)表中的
3、每一個形參都是由形參的數(shù)據(jù)類型和形參名來構成,形數(shù)個數(shù)可以是0,表示沒有形式參數(shù),但圓括號不能省略,也可以是1個或多個形參,但多個形參間要用逗號分隔。由花括號構成的是函數(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ù)體縮進函數(shù)類型函數(shù)名形參圖2.1 定義一個函數(shù)sum第3頁,共52頁,2022年,5月20日,11點0分,星期四2.1.1 函數(shù)定義需要說明的是:(1) C/C+不允許在一個函數(shù)體中再定義
4、函數(shù),即禁止嵌套定義,但允許嵌套調用。(2) 函數(shù)體也可不含有任何語句,這樣的函數(shù)稱為空函數(shù),它僅為程序結構而設定,本身沒有任何操作。(3) 函數(shù)類型決定了函數(shù)所需要的返回值類型,它可以是除數(shù)組類型之外的任何有效的C+數(shù)據(jù)類型,包括引用、指針等。一旦指定了函數(shù)類型,則須在函數(shù)體中通過return語句來指定函數(shù)的返回值,且返回值的類型應與函數(shù)類型相同,若返回值的類型與函數(shù)類型不相同,則程序按類型自動轉換方式轉換成函數(shù)的類型或將return后面的表達式進行強制轉換。(4) 若函數(shù)類型為void時,則表示該函數(shù)沒有返回值。但仍然可以在函數(shù)體中使用return語句“return;”,此時可將“retu
5、rn;”語句理解為是函數(shù)體花括號“”的作用,當流程遇到函數(shù)體的“”時,函數(shù)調用結束,控制權返回給主調函數(shù)。例如:void f1( int a)if (a 10)return;/ return;一旦執(zhí)行,后面的語句不再被執(zhí)行當a10條件滿足時,“return;”語句將控制權返回給主調函數(shù)。第4頁,共52頁,2022年,5月20日,11點0分,星期四2.1.2 函數(shù)的調用和聲明1. 函數(shù)的實參和形參定義一個函數(shù)就是為了以后的調用。調用函數(shù)時,先寫函數(shù)名,然后緊跟括號,括號里是實際調用該函數(shù)時所給定的參數(shù),稱為實際參數(shù),簡稱實參,并與形參相對應。要注意形參和實參的區(qū)別:(1) 從模塊概念來說,形參是
6、函數(shù)的接口,是存在于函數(shù)內(nèi)部的變量。而實參是存在于函數(shù)外部的變量。它們不是同一個實體,也就是說,形參變量和實參變量所對應的內(nèi)存空間不是同一個內(nèi)存空間。(2) 按函數(shù)定義時所指定的形參類型,實參除變量外還可以是數(shù)值或表達式等,而形參只能是變量。(3) 形參在函數(shù)調用之前是不存在的,只有在發(fā)生函數(shù)調用時,函數(shù)中的形參才會被分配內(nèi)存空間,然后執(zhí)行函數(shù)體中的語句,而當調用結束后,形參所占的內(nèi)存空間又會被釋放。2. 函數(shù)的調用函數(shù)調用的一般格式為:( )調用函數(shù)時要注意:實參與形參的個數(shù)應相等,類型應一致,且按順序對應,一一傳遞數(shù)據(jù)。例如,下面的示例用來輸出一個三角形的圖案。第5頁,共52頁,2022年
7、,5月20日,11點0分,星期四2.1.2 函數(shù)的調用和聲明 例Ex_Call 函數(shù)的調用#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;程序運行的結果如下: 第6頁,共52頁,2022年,5月20日,11點0分,星期四2.1.2 函數(shù)的調用和聲明代碼中,main函數(shù)的for循環(huán)語句共調
8、用了5次printline函數(shù)(A句),每次調用時因實參i+1值不斷改變,從而使函數(shù)printline打印出來的星號個數(shù)也隨之改變。printline函數(shù)由于沒有返回值,因此它作為一個語句來調用。事實上,對于有返回值的函數(shù)也可進行這種方式的調用,只是此時不使用返回值,僅要求函數(shù)完成一定的操作。實際上,在C+中,一個函數(shù)的調用方式還有很多。例如,對于前面sum函數(shù)還可有下列調用方式:int b = 2 * sum(4, 5);/ Bint c = 1; c = sum(c, sum(c, 4);/ C其中,B語句把函數(shù)作為表達式的一部分,并將返回值參與運算,結果b = 18;C是將函數(shù)作為函數(shù)的
9、實參,等價于“c = sum(1, sum(1,4);”,執(zhí)行sum(1,4)后,等價于“c = sum(1,5) ;”,最后結果為c = 6。3. 函數(shù)的聲明由于前面函數(shù)printline的定義代碼是放在main函數(shù)中調用語句A之前,因而A語句執(zhí)行不會有問題。但若將函數(shù)printline的定義代碼放在調用語句A之后,即函數(shù)定義在后,而調用在前,就會產(chǎn)生“printline標識符未定義”的編譯錯誤。此時必須在調用前進行函數(shù)聲明。第7頁,共52頁,2022年,5月20日,11點0分,星期四2.1.2 函數(shù)的調用和聲明聲明一個函數(shù)按下列格式進行: ( );可見,函數(shù)聲明的格式是在函數(shù)頭的后面加上分
10、號“;”。但要注意,函數(shù)聲明的內(nèi)容應和函數(shù)的定義應相同。例如,對于前面sum函數(shù)和最后一個printline函數(shù)可有如下聲明:int sum(int x, int y);void printline( char ch, int n );由于函數(shù)的聲明僅是對函數(shù)的原型進行說明,即函數(shù)原型聲明,其聲明的形參變量名在聲明語句中并沒有任何語句操作它,因此這里的形參名和函數(shù)的定義時的形參名可以不同,且函數(shù)聲明時的形參名還可以省略,但函數(shù)名、函數(shù)類型、形參類型及個數(shù)應與定義時相同。例如,下面幾種形式都是對sum函數(shù)原型的合法聲明:int sum(int a, int b); / 允許原型聲明時的形參名與定
11、義時不同int sum(int, int); / 省略全部形參名int sum(int a, int);/ 省略部分形參名int sum(int, int b);/ 省略部分形參名 不過,從程序的可讀性考慮,在聲明函數(shù)原型時,為每一個形參指定有意義的標識符,并且和函數(shù)定義時的參數(shù)名相同,是一個非常好的習慣。第8頁,共52頁,2022年,5月20日,11點0分,星期四2.1.3 值傳遞在C+中,函數(shù)的參數(shù)傳遞有兩種方式,一是按值傳遞,二是地址傳遞或引用傳遞。這里先來說明按值傳遞的參數(shù)傳遞方法,地址傳遞或引用傳遞在以后來討論。當函數(shù)的形參定義成一般變量時,如前面printline和sum函數(shù)的形參
12、都是一般變量,此時函數(shù)的參數(shù)傳遞就是按值傳遞方式,簡稱值傳遞,是指當一個函數(shù)被調用時,C+根據(jù)實參和形參的對應關系將實際參數(shù)的值一一傳遞給形參,供函數(shù)執(zhí)行時使用。值傳遞的特點是:(1) 若實參指定是變量,則傳遞的是實參變量的值而不是實參變量的地址。(2) 在執(zhí)行函數(shù)代碼時,由于對實參數(shù)據(jù)的操作最終是在形參的內(nèi)存空間中進行,因此形參值的改變只是改變了形參的內(nèi)存空間存儲的值,而不會改變實參變量所對應的內(nèi)存空間的值。也就是說,即使形參的值在函數(shù)中發(fā)生了變化,函數(shù)調用結束后,實參的值不會受到影響。例如:第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ù)調用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、程序的運行結果為:可以看出,雖然函數(shù)swap中交換了兩個形參x和y的值,但交換的結果并不能改變實參的值,所以調用該函數(shù)后,變量a和b的值仍然為原來的值。 函數(shù)值傳遞方式的最大好處是保持函數(shù)的獨立性。在值傳遞方式下,函數(shù)只有通過指定函數(shù)類型并在函數(shù)體中使用return來返回某一類型的數(shù)值。第11頁,共52頁,2022年,5月20日,11點0分,星期四2.1.4 函數(shù)的默認形參值在C+中,允許在函數(shù)的聲明或定義時給一個或多個參數(shù)指定默認值。這樣在調用時,可以不給出實際參數(shù),而按指定的默認值進行工作。例如:void delay(int loops = 1000)/ 函數(shù)定義,1000為形參loops
15、的默認值if ( 0 = loops) return;for (int i=0; iloops; i+);/ 空循環(huán),起延時作用這樣,當有調用delay();/ 和delay(1000)等效時,程序就會自動將loops當作成1000的默認值來進行處理。當然,也可在函數(shù)調用時指定相應的實際的參數(shù)值,例如:delay(2000);/ 形參loops的值為2000在設置函數(shù)的默認形參值時要注意:(1) 當函數(shù)既有原型聲明又有定義時,默認參數(shù)只能在原型聲明中指定,而不能在函數(shù)定義中指定。例如:void delay(int loops);/ 函數(shù)原型聲明/ void delay(int loops =
16、1000)/ 錯誤:此時不能函數(shù)定義中指定默認參數(shù)/ 第12頁,共52頁,2022年,5月20日,11點0分,星期四2.1.4 函數(shù)的默認形參值(2) 當一個函數(shù)中需要有多個默認參數(shù)時,則形參分布中,默認參數(shù)應嚴格從右到左逐次定義和指定,中間不能跳開。例如: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ù)設置默認值void display(int a,
17、 int b = 2, int c);/ 錯誤:默認參數(shù)應從最右邊開始void display(int a = 1, int b = 2, int c);/ 錯誤:默認參數(shù)應從最右邊開始void display(int a = 1, int b, int c = 3);/ 錯誤:多個默認參數(shù)中間不能有非默認參數(shù)(3) 當帶有默認參數(shù)的函數(shù)調用時,系統(tǒng)按從左到右的順序將實參與形參結合,當實參的數(shù)目不足時,系統(tǒng)將按同樣的順序用聲明或定義中的默認值來補齊所缺少的參數(shù)。第13頁,共52頁,2022年,5月20日,11點0分,星期四2.1.4 函數(shù)的默認形參值例Ex_Default 在函數(shù)定義中設置多個
18、默認參數(shù)#include using namespace std;void display(int a, int b = 2, int c = 3)/ 在函數(shù)定義中設置默認參數(shù)couta = a, b = b, c = cn;int main()display(1);display(1, 5);display(1, 7, 9);return 0;程序的運行結果如下:第14頁,共52頁,2022年,5月20日,11點0分,星期四2.1.4 函數(shù)的默認形參值(4) 由于對同一個函數(shù)的原型可作多次聲明,因此在函數(shù)聲明中指定多個默認參數(shù)時,可用多條函數(shù)原型聲明語句來指定,但同一個參數(shù)的默認值只能指定一
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為默認參數(shù)void display(int a, int b=2, int c);/ 指定b為默認參數(shù)第15頁,共52頁,2022年,5月20日,11點0分,星期四 2.2 C+函數(shù)特性 函數(shù)重載(overloaded)是C+對C的擴展,它允許多個同名的函數(shù)存在,但同名的各個函數(shù)的形參必須有區(qū)別:要么形
20、參的個數(shù)不同;要么形參的個數(shù)相同,但參數(shù)類型有所不同。 例Ex_OverLoad 編程求兩個或三個操作數(shù)之和程序的運行結果為: 從上面的例子可以看出:由于使用了函數(shù)的重載,因而不僅方便函數(shù)名的記憶,而且更主要的是完善了同一個函數(shù)的代碼功能,給調用帶來了許多方便。程序中各種形式的sum函數(shù)都稱為sum的重載函數(shù)。需要說明的是:(1) 重載函數(shù)必須具有不同的參數(shù)個數(shù)或不同的參數(shù)類型,若只有返回值的類型不同是不行的。例如:void fun(int a, int b);int fun(int a, int b);是錯誤的。因為如果有函數(shù)調用fun(2, 3)時,編譯器無法準確地確定應調用哪一個函數(shù)。(
21、2) 當函數(shù)的重載帶有默認參數(shù)時,也要應該注意避免上述的二義性情況。例如:int fun(int a, int b = 0);int fun(int a);是錯誤的。因為如果有函數(shù)調用fun(2)時,編譯器也是無法準確地確定應調用哪一個函數(shù)。第16頁,共52頁,2022年,5月20日,11點0分,星期四2.2.2 函數(shù)嵌套調用C+允許在函數(shù)中再調用其他函數(shù),這種調用稱為函數(shù)的嵌套調用。例如,下面的示例是通過多個函數(shù)以及函數(shù)的嵌套調用來求解一元二次方程的根。 例Ex_Root 函數(shù)嵌套調用:求解一元二次方程的根本例main函數(shù)中調用了root函數(shù),root函數(shù)中又調用了sdelta和print函
22、數(shù),而sdelta函數(shù)還調用了cmath頭文件定義的庫函數(shù)sqrt(求平方根)和fabs(求浮點數(shù)的絕對值)。它們的調用關系如圖2.2所示。main函數(shù)root函數(shù)sdelta函數(shù)fabs庫函數(shù)print函數(shù)sqrt庫函數(shù)圖2.2 例Ex_Root中的各函數(shù)調用的關系第17頁,共52頁,2022年,5月20日,11點0分,星期四2.2.2 函數(shù)嵌套調用函數(shù)print用來輸出根的信息,當n=0時,參數(shù)r1和r2無效,但調用該函數(shù)時還必須指定相應的實際參數(shù),只是此時的實參值在函數(shù)執(zhí)行中不起作用。當n=1時,只有參數(shù)r1有效,而當n=2時,參數(shù)r1和r2才會都有效。函數(shù)sdelta用來計算一元二次方
23、程的系數(shù)a、b和c的b2-4ac的平方根。由于“d = b*b - 4.0 * a * c;”計算誤差,d值不一定剛好等于0.0,因此調用庫函數(shù)fabs求d的絕對值,并當小于1.0e-10(1.0 x1010)時,將d值視為0.0,并返回0.0。當d值大于0.0時,函數(shù)返回其平方根。當d值小于0.0時,由于無法求出實平方根,因此作為程序技巧,函數(shù)返回-1.0。這樣當在root函數(shù)中調用時,通過返回值的判斷來決定有無方程根。root函數(shù)用來求解一元二次方程的方程根并輸出,函數(shù)設計時要考慮:有無根、同根、不同根、系數(shù)a為0以及系數(shù)b為0等多種情況。程序運行的結果如下: 第18頁,共52頁,2022
24、年,5月20日,11點0分,星期四2.2.3 遞歸函數(shù)C+允許在調用一個函數(shù)的過程中出現(xiàn)直接地或間接地調用函數(shù)本身,這種情況稱為函數(shù)的遞歸調用。遞歸(Recursion)是一種常用的程序方法(算法),相應的函數(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中,當n不等于0時,又調用了該函數(shù)本身。下面來分析此函數(shù)的執(zhí)行過程:(1) 因n = 4,不等于0,故執(zhí)行“result = 4*factorial(3);”,函數(shù)返回的值為4*factorial(3),即factorial(4) = 4*factorial(3);(2) 調用“factorial(3);”, n = 3不等于0,執(zhí)行“result=3*factorial(2);”,函數(shù)返回的值為3*factorial(2) ,即
26、factorial(3) =3*factorial(2);(3) 調用“factorial(2);”, n = 2不等于0,執(zhí)行“result=2*factorial(1);”, 函數(shù)返回的值為2*factorial(1) ,即factorial(2) =2*factorial(1);(4) 調用“factorial(1);”,n = 1不等于0,執(zhí)行“result=1*factorial(0);”, 函數(shù)返回的值為1*factorial(0) ,即factorial(1) =1*factorial(0);(5) 調用“factorial(0);”,n等于0,結果函數(shù)返回的值為1。上述過程是根
27、據(jù)程序運行過程進行推算的,這個過程稱為“遞推”過程。函數(shù)的遞歸調用在遞推過程后還進行另一稱為“回歸”的過程,它是按“遞推”的逆過程,逐一求值回歸,一直到達遞推的開始處。因此,當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,結果為4!,值為24。第20頁,共52頁,2022年,5月20日,11點0分,星期四2.2.3 遞歸函數(shù)以上的例子可以看出,函數(shù)的遞歸調用能使程序精巧、高效。但要注意,遞歸函數(shù)中必須要有結束遞歸過程的條件,否則遞
28、歸會無限制地進行下去。例如,在上述代碼中,if (n=0) result=1;就是結束遞歸過程的條件,若函數(shù)factorial變?yōu)椋簂ong factorial(int n)long result=0;result = n*factorial(n-1);return result;則遞歸會無限制地進行下去,此程序將變得毫無用途。需要說明的是:雖然遞歸調用編寫的程序簡潔清晰,但每次調用函數(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í)行過程中,調用函數(shù)時首先需要保存主調函
29、數(shù)的現(xiàn)場和返回地址,然后程序轉移到被調函數(shù)的起始地址繼續(xù)執(zhí)行。被調函數(shù)執(zhí)行結束后,先恢復主調函數(shù)的現(xiàn)場,取出返回地址并將返回值賦給函數(shù)調用本身,最后在返回地址處開始繼續(xù)執(zhí)行。當函數(shù)體比較小且執(zhí)行的功能比較簡單時,這種函數(shù)調用方式的系統(tǒng)開銷相對較大。為了解決這一問題,C+引入了內(nèi)聯(lián)函數(shù)的概念,它把函數(shù)體的代碼直接插入到調用處,將調用函數(shù)的方式改為順序執(zhí)行直接插入的程序代碼,這樣可以減少程序的執(zhí)行時間,但同時增加了代碼的實際長度。內(nèi)聯(lián)函數(shù)的使用方法與一般函數(shù)相同,只是在內(nèi)聯(lián)函數(shù)定義時,需在函數(shù)的類型前面加上inline關鍵字。例如: 例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;程序的運行結果如下: 在使用內(nèi)聯(lián)函數(shù)時,還需要注意的是:(1) 內(nèi)聯(lián)函數(shù)也要遵循定義在前,調用在后的原則。形參與實參之間的關系與一般函數(shù)相同。(2) 關鍵字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、和復雜嵌套的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)常被調用的、大多可在一行寫完的函數(shù),并常用來代替以后要討論的帶參數(shù)的宏定義。第23頁,共52頁,2022年,5月20日,11點0分,星期四2.3 作用域和存儲類型作用域又稱作用范圍,是指程序中標識符(變量名、函數(shù)名、數(shù)組名、類名、對象名等)的有效范圍。一個標識符是否可以被引用,稱之為標識符的可見性。在一個C+程序項目中,一個標識符只能在聲明或定義它的范圍內(nèi)可見,在此之外是不可見的。根據(jù)標識符的作用范圍,可將其作用域分為5種
32、:函數(shù)原型作用域、函數(shù)作用域、塊作用域、類作用域和文件作用域。其中,類作用域將在以后介紹,這里介紹其他幾種。1. 函數(shù)原型作用域函數(shù)原型作用域指的是在聲明函數(shù)原型所指定的參數(shù)標識符的作用范圍。這個作用范圍是在函數(shù)原型聲明中的左、右圓括號之間。正因為如此,在函數(shù)原型中聲明的標識符可以與函數(shù)定義中說明的標識符名稱不同。由于所聲明的標識符與該函數(shù)的定義及調用無關,所以可以在函數(shù)原型聲明中只作參數(shù)的類型聲明,而省略參數(shù)名。例如:double max(double x, double y);和double max(double, double);是等價的。2. 函數(shù)作用域具有函數(shù)作用域的標識符在聲明它的
33、函數(shù)內(nèi)可見,但在此函數(shù)之外是不可見的。在C+語言中,只有goto語句使用的標號是惟一具有函數(shù)作用域的標識符。2.3.1作用域第24頁,共52頁,2022年,5月20日,11點0分,星期四2.3.1 作用域這里的塊就是由“”和“”組成的塊語句(復合語句)。在塊中聲明的標識符,其作用域從聲明處開始,一直到結束塊的花括號為止。塊作用域也稱作局部作用域,具有塊作用域的變量是局部變量。例如: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語句結束處終止。a的作用域b的作用域第25頁,共52頁,2022年,5月20日,11點0分,星期四2.3.1 作用域需要說明的是:當標識符的作用域完全相同時,不允許出現(xiàn)相同的標識符名。而當標識符具有不同的作用域時,卻允許標識符同名。例如:void fun(void)塊A塊B/ 塊A開始int i;/ 塊B開始int i;i = 100;/ 塊B結束/ 塊A結束代碼中,在A和B塊中都聲
35、明了變量i,這是允許的,因為塊A和塊B不是同一個作用域。但同時出現(xiàn)另外一個問題,語句“i = 100;”中的i是使用A塊中的變量i還是使用B中的變量i?C+規(guī)定在這種作用域嵌套的情況下,如果內(nèi)層(塊B)和外層(塊A)作用域聲明了同名的標識符,那么在外層作用域中聲明的標識符對于該內(nèi)層作用域是不可見的。也就是說,在塊B聲明的變量i與塊A聲明的變量i無關,當塊B中的i=100時,不會影響塊A中變量i的值。塊A塊B第26頁,共52頁,2022年,5月20日,11點0分,星期四2.3.1 作用域4. 文件作用域在所有函數(shù)外定義的標識符稱為全局標識符。全局標識符的作用域是文件作用域,它從聲明之處開始,直到
36、文件結束一直是可見的。具有文件作用域的變量和常量稱為全局變量和全局常量,例如:const float PI = 3.14;/ 全局常量PI,其作用域從此開始到文件結束int a;/ 全局變量a,其作用域從此開始到文件結束void main( ) / void funA(int x) / 其中,全局常量PI和全局變量a的作用域是文件作用域。標識符的文件作用域一般還有以下幾種情況:第27頁,共52頁,2022年,5月20日,11點0分,星期四2.3.1 作用域(1) 若函數(shù)定義在后,調用在前,必須進行函數(shù)原型聲明。若函數(shù)定義在前,調用在后,函數(shù)定義包含了函數(shù)的原型聲明。一旦聲明了函數(shù)原型,函數(shù)標識
37、符的作用域是從定義開始到源程序文件結束。例如:void funA(int x ); / 函數(shù)funA的作用域從此開始到文件結束void funB( ) / 函數(shù)funA的作用域從此開始到文件結束/ void main( ) / void funA(int x) / (2) 對于在頭文件中定義的標識符,當它們被預編譯時,會將頭文件的內(nèi)容在源文件的相應位置展開,所以在頭文件中定義的標識符的作用域可以看成從#include該頭文件開始的位置到源程序文件結束。例如,以前示例中頭文件iostream的std:cin和std:cout的作用域是從#include預處理指令開始一直到源程序文件結束。 注意,
38、若使用ANSI/ISO C+新文件格式的包含,則cin和cout的作用域是從using語句開始一直到源程序文件結束。第28頁,共52頁,2022年,5月20日,11點0分,星期四2.3.2 域運算符在C+中,若在塊作用域內(nèi)使用與局部標識符同名的塊外標識符時,則須使用域運算符“:”來引用,且該標識符一定要是全局標識符,即它具有文件作用域。例如: 例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; 程序的運行結果為:需要說明的是,域運算符“:”往往還用于指定引用對象所屬的類、名稱空間等。第29頁,共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型存儲類型是針對變量而言的,它規(guī)定了變量的生存期。無論是全局變量還是局部變量,編譯系統(tǒng)往往根據(jù)其存儲方式定義、分配和釋放相應的內(nèi)存空間。變量的存儲類型反映了變量在哪開辟內(nèi)存空間以及占用內(nèi)存空間的有效
40、期限。在C+中,變量有4種存儲類型:自動類型、靜態(tài)類型、寄存器類型和外部類型,這些存儲類型是在變量定義時來指定的,其一般格式如下: ; 1. 自動類型和寄存器類型一般說來,用自動存儲類型聲明的變量都是限制在某個程序范圍內(nèi)使用,即為局部變量。從系統(tǒng)角度來說,自動存儲類型變量是采用動態(tài)分配方式在棧區(qū)中來分配內(nèi)存空間。因此,當程序執(zhí)行到超出該變量的作用域時,就釋放它所占用的內(nèi)存空間,其值也隨之消失了。在C+語言中,聲明一個自動存儲類型的變量是在變量類型前加上關鍵字auto,例如:autoint i;若自動存儲類型的變量是在函數(shù)內(nèi)或語句塊中聲明的,則可省略關鍵字auto,例如:void fun()in
41、t i;/ 省略auto/ 第30頁,共52頁,2022年,5月20日,11點0分,星期四2.3.3 存儲類型使用關鍵字register聲明寄存器類型的變量的目的是將所聲明的變量放入寄存器內(nèi),從而加快程序的運行速度。例如:register int i;/ 聲明寄存器類型變量但有時,在使用register聲明時,若系統(tǒng)寄存器已經(jīng)被其他數(shù)據(jù)占據(jù)時,寄存器類型的變量就會自動當作auto變量。2. 靜態(tài)類型從變量的生存期來說,一個變量的存儲空間可以是永久的,即在程序運行期間該變量一直存在,如全局變量;也可以是臨時的,如局部變量,當流程執(zhí)行到它的說明語句時,系統(tǒng)為其在棧區(qū)中動態(tài)分配一個臨時的內(nèi)存空間,并
42、在它的作用域中有效,一旦流程超出該變量的作用域時,就釋放它所占用的內(nèi)存空間,其值也隨之消失。但是,若在聲明局部變量類型前面加上關鍵字static,則將其定義成了一個靜態(tài)類型的變量。這樣的變量雖具有局部變量的作用域,但由于它是用靜態(tài)分配方式在靜態(tài)數(shù)據(jù)區(qū)中來分配內(nèi)存空間。因此,在這種方式下,只要程序還在繼續(xù)執(zhí)行,靜態(tài)類型變量的值就一直有效,不會隨它所在的函數(shù)或語句塊的結束而消失。簡單地說,靜態(tài)類型的局部變量雖具有局部變量的作用域,但卻有全局變量的生存期。 值得注意的是,如需定義一個很大的數(shù)組時,則應將數(shù)組定義成全局數(shù)組或將數(shù)組的存儲類型定義成static,而不應定義成自動存儲類型或局部數(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í)行時進行初始化,正因為如此,在聲明靜態(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 存儲類型程序中,當?shù)?次調用函數(shù)count時,由于變量j是靜態(tài)類型,因此其初值設為0后不再進行初始化,執(zhí)行j+后,j值為1,并一直有效。第2次調用函數(shù)count時,由于j已分配內(nèi)存且進行過初始化,因此語句“static int j = 0;”被跳過,執(zhí)行j+后,j值為2。故程序運行結果為: 事實上,在程序中聲明的全局變量總是靜態(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)建一個控制臺應用程序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+應用程序向導自動添加的。stdafx.h是每個Visual C+應用程序所必有的預編譯頭文件,程序所用到的Visual C+頭文件包含語句一般均應添加到這個文件中。函數(shù)f先在該文件中作函數(shù)的原型聲明,函數(shù)的定義在另一個文件中,這是Visual C+所允許的。選擇“文件”“新建”菜單命令,默認時會自
47、動將“新建”對話框切換到“文件”頁面,選中“C+ Source File”文件類型,在文件編輯框中輸入Ex_StaticScope_1.cpp,如圖2.3所示。單擊確定按鈕,在Ex_StaticScope_1.cpp中添加下列代碼:#include stdafx.h#include using namespace std;static int 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運行后,其結果如下: 可見,函數(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. 外部類型使用關鍵字extern聲明的變量稱為外部變量,一般是指定義在本程序外部的變
49、量。當某個變量被聲明成外部變量時,不必再次為它分配內(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 存儲類型運行結果為: 第二種情況:當由多個文件組成一個完整的程序時,在一個源程序文件中定義的變量要被其他若干個源文件引用時,引用的文件中要用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)運行后,結果如下: 需要注意的是:(1) 可以對同一個變量進行多次extern的聲明。若在聲明時,給一個外部變量賦初值,則編譯器認為是一個具體的變量定義,而不是一個外部
52、變量的聲明,此時要注意同名標識符的重復定義。例如:extern int n = 1;/ 變量定義int n;/ 錯誤:變量n重復定義(2) 雖然外部變量對不同源文件中或函數(shù)之間的數(shù)據(jù)傳遞特別有用。但也應該看到,這種能被許多函數(shù)共享的外部變量,其數(shù)值的任何一次改變,都將影響到所有引用此變量的函數(shù)的執(zhí)行結果,其危險性是顯然的。 第39頁,共52頁,2022年,5月20日,11點0分,星期四2.4 名稱空間在C+中,定義一個名稱空間的格式如下:2.4.1 名稱空間的定義namespace 標識符成員;體其中,namespace是C+關鍵字,標識符用作名稱空間的名稱,屬于該名稱空間體中的變量、函數(shù)、結
53、構、枚舉、聯(lián)合以及以后要討論的類等都可以認為是該名稱空間的成員。需要說明的是:第40頁,共52頁,2022年,5月20日,11點0分,星期四2.4.1 名稱空間的定義(1) 同一個文件中,可以允許定義多個名稱空間。一旦定義名稱空間后,標識符就標識名稱空間體的那個區(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來標識各自所在的名稱區(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)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 計劃生育基層工作人員培訓與發(fā)展考核試卷
- 家庭教育家長會核心要點解析
- 羊毛纖維性能研究考核試卷
- 楊漢清比較教育學理論體系
- 蔬菜加工自動化生產(chǎn)線設計考核試卷
- 口腔清潔用品消費者行為與購物心理考核試卷
- 2025年直播電商項目建議書
- 2025年記錄儀表項目發(fā)展計劃
- 多詞語馬賽克技術解析與應用
- 2019-2025年企業(yè)人力資源管理師之四級人力資源管理師考前沖刺試卷A卷含答案
- 超合同30簽補充協(xié)議
- 2025年國家義務教育質量監(jiān)測中學語文理論考核試題
- 2025年山東省淄博市中考二模地理試題及答案
- 2025執(zhí)業(yè)醫(yī)師資格考試練習題庫完美版含答案
- 2025屆全國百校聯(lián)盟高考仿真模擬英語試卷含解析
- 2025年帆船教練技能與知識考核試題集
- 學習教育查擺問題清單及整改措施14條
- 廣投集團招聘筆試題庫2025
- 罪犯心理健康教育課件
- 安徽省立醫(yī)院醫(yī)技及醫(yī)輔人員招聘考試真題2024
- GB/T 45495-2025消費品缺陷工程分析銳利邊緣測試方法
評論
0/150
提交評論