版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、精選優(yōu)質(zhì)文檔-傾情為你奉上第4章 函數(shù)與預(yù)處理4.1 概述4.2 定義函數(shù)的一般形式4.3 函數(shù)參數(shù)和函數(shù)的值4.4 函數(shù)的調(diào)用*4.5 內(nèi)置函數(shù)*4.6 函數(shù)的重載*4.7 函數(shù)模板*4.8 有默認(rèn)參數(shù)的函數(shù)4.9 函數(shù)的嵌套調(diào)用4.10 函數(shù)的遞歸調(diào)用4.11 局部變量和全局變量4.12 變量的存儲類別4.13 變量屬性小結(jié)4.14 關(guān)于變量的聲明和定義4.15 內(nèi)部函數(shù)和外部函數(shù)4.16 預(yù)處理命令4.1 概述一個較大的程序不可能完全由一個人從頭至尾地完成,更不可能把所有的內(nèi)容都放在一個主函數(shù)中為了便于規(guī)劃組織編程和調(diào)試,一般的做法是把一個大的程序劃分為若干個程序模塊(即程序文件),每一
2、個模塊實現(xiàn)一部分功能不同的程序模塊可以由不同的人來完成在程序進(jìn)行編譯時,以程序模塊為編譯單位,即分別對每一個編譯單位進(jìn)行編譯如果發(fā)現(xiàn)錯誤,可以在本程序模塊范圍內(nèi)查錯并改正在分別通過編譯后,才進(jìn)行連接,把各模塊的目標(biāo)文件以及系統(tǒng)文件連接在一起形成可執(zhí)行文件在一個程序文件中可以包含若干個函數(shù)無論把一個程序劃分為多少個程序模塊,只能有一個main函數(shù)程序總是從main函數(shù)開始執(zhí)行的在程序運行過程中,由主函數(shù)調(diào)用其他函數(shù),其他函數(shù)也可以互相調(diào)用在C語言中沒有類和對象,在程序模塊中直接定義函數(shù)可以認(rèn)為,一個C程序是由若干個函數(shù)組成的,C語言被認(rèn)為是面向函數(shù)的語言C+面向過程的程序設(shè)計沿用了C語言使用函數(shù)
3、的方法在C+面向?qū)ο蟮某绦蛟O(shè)計中,主函數(shù)以外的函數(shù)大多是被封裝在類中的主函數(shù)或其他函數(shù)可以通過類對象調(diào)用類中的函數(shù)無論是C還是C+,程序中的各項操作基本上都是由函數(shù)來實現(xiàn)的,程序編寫者要根據(jù)需要編寫一個個函數(shù),每個函數(shù)用來實現(xiàn)某一功能因此,讀者必須掌握函數(shù)的概念以及學(xué)會設(shè)計和使用函數(shù) “函數(shù)”這個名詞是從英文function翻譯過來的,其實function的原意是“功能”顧名思義,一個函數(shù)就是一個功能在實際應(yīng)用的程序中,主函數(shù)寫得很簡單,它的作用就是調(diào)用各個函數(shù),程序各部分的功能全部都是由各函數(shù)實現(xiàn)的主函數(shù)相當(dāng)于總調(diào)度,調(diào)動各函數(shù)依次實現(xiàn)各項功能開發(fā)商和軟件開發(fā)人員將一些常用的功能模塊編寫成函
4、數(shù),放在函數(shù)庫中供公共選用程序開發(fā)人員要善于利用庫函數(shù),以減少重復(fù)編寫程序段的工作量圖4.1是一個程序中函數(shù)調(diào)用的示意圖圖4.1例4.1 在主函數(shù)中調(diào)用其他函數(shù)#include <iostream>using namespace std;void printstar(void) /定義printstar函數(shù) cout<<* <<endl; /輸出30個“*”void print_message(void) /定義print_message函數(shù) cout<<Welcome to C+!<<endl; /輸出一行文字int main(vo
5、id)printstar( ); /調(diào)用printstar 函數(shù) print_message( ); /調(diào)用print_message函數(shù)printstar( ); /調(diào)用printstar 函數(shù)return 0;運行情況如下:*Welcome to C+!*從用戶使用的角度看,函數(shù)有兩種:(1) 系統(tǒng)函數(shù),即庫函數(shù)這是由編譯系統(tǒng)提供的,用戶不必自己定義這些函數(shù),可以直接使用它們(2) 用戶自己定義的函數(shù)用以解決用戶的專門需要從函數(shù)的形式看,函數(shù)分兩類:(1) 無參函數(shù)調(diào)用函數(shù)時不必給出參數(shù)(2) 有參函數(shù)在調(diào)用函數(shù)時,要給出參數(shù)在主調(diào)函數(shù)和被調(diào)用函數(shù)之間有數(shù)據(jù)傳遞4.2 定義函數(shù)的一般形式
6、4.2.1 定義無參函數(shù)的一般形式定義無參函數(shù)的一般形式為類型標(biāo)識符 函數(shù)名(void)聲明部分 語句 例4.1中的printstar和print_message函數(shù)都是無參函數(shù)用類型標(biāo)識符指定函數(shù)的類型,即函數(shù)帶回來的值的類型4.2.2 定義有參函數(shù)的一般形式定義有參函數(shù)的一般形式為類型標(biāo)識符 函數(shù)名(形式參數(shù)表列)聲明部分語句 例如:int max(int x,int y) /函數(shù)首部,函數(shù)值為整型,有兩個整型形參int z; /函數(shù)體中的聲明部分 z=x>y?x:y; /將x和y中的大者的值賦給整型變量zreturn (z);/將z的值作為函數(shù)值返回調(diào)用點C+要求在定義函數(shù)時必須指
7、定函數(shù)的類型4.3 函數(shù)參數(shù)和函數(shù)的值 4.3.1 形式參數(shù)和實際參數(shù)在調(diào)用函數(shù)時,大多數(shù)情況下,函數(shù)是帶參數(shù)的主調(diào)函數(shù)和被調(diào)用函數(shù)之間有數(shù)據(jù)傳遞關(guān)系前面已提到:在定義函數(shù)時函數(shù)名后面括號中的變量名稱為形式參數(shù)(formal parameter,簡稱形參),在主調(diào)函數(shù)中調(diào)用一個函數(shù)時,函數(shù)名后面括號中的參數(shù)(可以是一個表達(dá)式)稱為實際參數(shù)(actual parameter,簡稱實參)例4.2 調(diào)用函數(shù)時的數(shù)據(jù)傳遞#include <iostream>using namespace std;int max(int x,int y) /定義有參函數(shù)maxint z; z=x>y?
8、x:y; return(z);int main( )int a,b,c; cout<<please enter two integer numbers:; cin>>a>>b; c=max(a,b);/調(diào)用max函數(shù),給定實參為a,b函數(shù)值賦給c cout<<max=<<c<<endl; return 0;運行情況如下:please enter two integer numbers:2 3max=3圖4.2有關(guān)形參與實參的說明:(1) 在定義函數(shù)時指定的形參,在未出現(xiàn)函數(shù)調(diào)用時,它們并不占內(nèi)存中的存儲單元,因此稱它們是形
9、式參數(shù)或虛擬參數(shù),表示它們并不是實際存在的數(shù)據(jù),只有在發(fā)生函數(shù)調(diào)用時,函數(shù)max中的形參才被分配內(nèi)存單元,以便接收從實參傳來的數(shù)據(jù)在調(diào)用結(jié)束后,形參所占的內(nèi)存單元也被釋放(2) 實參可以是常量變量或表達(dá)式,如max(3, a+b);但要求a和b有確定的值以便在調(diào)用函數(shù)時將實參的值賦給形參(3) 在定義函數(shù)時,必須在函數(shù)首部指定形參的類型(見例4.2程序第3行)(4) 實參與形參的類型應(yīng)相同或賦值兼容例4.2中實參和形參都是整型,這是合法的正確的如果實參為整型而形參為實型,或者相反,則按不同類型數(shù)值的賦值規(guī)則進(jìn)行轉(zhuǎn)換例如實參a的值為3.5,而形參x為整型,則將3.5轉(zhuǎn)換成整數(shù)3,然后送到形參b字
10、符型與整型可以互相通用(5) 實參變量對形參變量的數(shù)據(jù)傳遞是“值傳遞”,即單向傳遞,只由實參傳給形參,而不能由形參傳回來給實參在調(diào)用函數(shù)時,編譯系統(tǒng)臨時給形參分配存儲單元請注意: 實參單元與形參單元是不同的單元圖4.3表示將實參a和b的值2和3傳遞給對應(yīng)的形參x和y 圖4.3 圖4.4調(diào)用結(jié)束后,形參單元被釋放,實參單元仍保留并維持原值因此,在執(zhí)行一個被調(diào)用函數(shù)時,形參的值如果發(fā)生改變,并不會改變主調(diào)函數(shù)中實參的值例如,若在執(zhí)行max函數(shù)過程中形參x和y的值變?yōu)?0和15,調(diào)用結(jié)束后,實參a和b仍為2和3,見圖4.44.3.2 函數(shù)的返回值 (1) 函數(shù)的返回值是通過函數(shù)中的return語句獲
11、得的return語句將被調(diào)用函數(shù)中的一個確定值帶回主調(diào)函數(shù)中去return語句后面的括號可以要,也可以不要return后面的值可以是一個表達(dá)式(2) 函數(shù)值的類型既然函數(shù)有返回值,這個值當(dāng)然應(yīng)屬于某一個確定的類型,應(yīng)當(dāng)在定義函數(shù)時指定函數(shù)值的類型(3) 如果函數(shù)值的類型和return語句中表達(dá)式的值不一致,則以函數(shù)類型為準(zhǔn),即函數(shù)類型決定返回值的類型對數(shù)值型數(shù)據(jù),可以自動進(jìn)行類型轉(zhuǎn)換4.4 函數(shù)的調(diào)用 4.4.1 函數(shù)調(diào)用的一般形式函數(shù)名(實參表列)如果是調(diào)用無參函數(shù),則“實參表列”可以沒有,但括號不能省略如果實參表列包含多個實參,則各參數(shù)間用逗號隔開實參與形參的個數(shù)應(yīng)相等,類型應(yīng)匹配(相同或
12、賦值兼容)實參與形參按順序?qū)?yīng),一對一地傳遞數(shù)據(jù)但應(yīng)說明,如果實參表列包括多個實參,對實參求值的順序并不是確定的4.4.2 函數(shù)調(diào)用的方式按函數(shù)在語句中的作用來分,可以有以下3種函數(shù)調(diào)用方式:1. 函數(shù)語句把函數(shù)調(diào)用單獨作為一個語句,并不要求函數(shù)帶回一個值,只是要求函數(shù)完成一定的操作如例4.1中的printstar( );2. 函數(shù)表達(dá)式函數(shù)出現(xiàn)在一個表達(dá)式中,這時要求函數(shù)帶回一個確定的值以參加表達(dá)式的運算如c=2*max(a,b);3. 函數(shù)參數(shù)函數(shù)調(diào)用作為一個函數(shù)的實參如m=max(a,max(b,c); /max(b,c)是函數(shù)調(diào)用,其值作為外層max函數(shù)調(diào)用的一個實參4.4.3 對被調(diào)
13、用函數(shù)的聲明和函數(shù)原型在一個函數(shù)中調(diào)用另一個函數(shù)(即被調(diào)用函數(shù))需要具備哪些條件呢?(1) 首先被調(diào)用的函數(shù)必須是已經(jīng)存在的函數(shù)(2) 如果使用庫函數(shù),一般還應(yīng)該在本文件開頭用#include命令將有關(guān)頭文件“包含”到本文件中來(3) 如果使用用戶自己定義的函數(shù),而該函數(shù)與調(diào)用它的函數(shù)(即主調(diào)函數(shù))在同一個程序單位中,且位置在主調(diào)函數(shù)之后,則必須在調(diào)用此函數(shù)之前對被調(diào)用的函數(shù)作聲明所謂函數(shù)聲明(declare),就是在函數(shù)尚在未定義的情況下,事先將該函數(shù)的有關(guān)信息通知編譯系統(tǒng),以便使編譯能正常進(jìn)行例4.3 對被調(diào)用的函數(shù)作聲明#include <iostream>using nam
14、espace std;int main( )float add(float x,float y); /對add函數(shù)作聲明 float a,b,c;cout<<please enter a,b:; cin>>a>>b; c=add(a,b); cout<<sum=<<c<<endl; return 0;float add(float x,float y)/定義add函數(shù)float z; z=x+y; return (z);運行情況如下:please enter a,b:123.68 456.45sum=580.13注意:對函
15、數(shù)的定義和聲明不是同一件事情定義是指對函數(shù)功能的確立,包括指定函數(shù)名函數(shù)類型形參及其類型函數(shù)體等,它是一個完整的獨立的函數(shù)單位而聲明的作用則是把函數(shù)的名字函數(shù)類型以及形參的個數(shù)類型和順序(注意,不包括函數(shù)體)通知編譯系統(tǒng),以便在對包含函數(shù)調(diào)用的語句進(jìn)行編譯時,據(jù)此對其進(jìn)行對照檢查(例如函數(shù)名是否正確,實參與形參的類型和個數(shù)是否一致)其實,在函數(shù)聲明中也可以不寫形參名,而只寫形參的類型,如float add(float,float);這種函數(shù)聲明稱為函數(shù)原型(function prototype)使用函數(shù)原型是C和C+的一個重要特點它的作用主要是: 根據(jù)函數(shù)原型在程序編譯階段對調(diào)用函數(shù)的合法性進(jìn)
16、行全面檢查如果發(fā)現(xiàn)與函數(shù)原型不匹配的函數(shù)調(diào)用就報告編譯出錯它屬于語法錯誤用戶根據(jù)屏幕顯示的出錯信息很容易發(fā)現(xiàn)和糾正錯誤函數(shù)原型的一般形式為(1) 函數(shù)類型 函數(shù)名(參數(shù)類型1,參數(shù)類型2);(2) 函數(shù)類型 函數(shù)名(參數(shù)類型1 參數(shù)名1,參數(shù)類型2 參數(shù)名2);第(1)種形式是基本的形式為了便于閱讀程序,也允許在函數(shù)原型中加上參數(shù)名,就成了第(2)種形式但編譯系統(tǒng)并不檢查參數(shù)名因此參數(shù)名是什么都無所謂上面程序中的聲明也可以寫成float add(float a,float b); /參數(shù)名不用xy,而用ab 效果完全相同應(yīng)當(dāng)保證函數(shù)原型與函數(shù)首部寫法上的一致,即函數(shù)類型函數(shù)名參數(shù)個數(shù)參數(shù)類型和
17、參數(shù)順序必須相同在函數(shù)調(diào)用時函數(shù)名實參類型和實參個數(shù)應(yīng)與函數(shù)原型一致說明: (1) 前面已說明,如果被調(diào)用函數(shù)的定義出現(xiàn)在主調(diào)函數(shù)之前,可以不必加以聲明因為編譯系統(tǒng)已經(jīng)事先知道了已定義的函數(shù)類型,會根據(jù)函數(shù)首部提供的信息對函數(shù)的調(diào)用作正確性檢查有經(jīng)驗的程序編制人員一般都把main函數(shù)寫在最前面,這樣對整個程序的結(jié)構(gòu)和作用一目了然,統(tǒng)覽全局,然后再具體了解各函數(shù)的細(xì)節(jié)此外,用函數(shù)原型來聲明函數(shù),還能減少編寫程序時可能出現(xiàn)的錯誤由于函數(shù)聲明的位置與函數(shù)調(diào)用語句的位置比較近,因此在寫程序時便于就近參照函數(shù)原型來書寫函數(shù)調(diào)用,不易出錯所以應(yīng)養(yǎng)成對所有用到的函數(shù)作聲明的習(xí)慣這是保證程序正確性和可讀性的重
18、要環(huán)節(jié)(2) 函數(shù)聲明的位置可以在調(diào)用函數(shù)所在的函數(shù)中,也可以在函數(shù)之外如果函數(shù)聲明放在函數(shù)的外部,在所有函數(shù)定義之前,則在各個主調(diào)函數(shù)中不必對所調(diào)用的函數(shù)再作聲明例如: char letter(char,char); /本行和以下兩行函數(shù)聲明在所有函數(shù)之前且在函數(shù)外部float f(float,float); /因而作用域是整個文件 int i(float, float); int main( )/在main函數(shù)中不必對它所調(diào)用的函數(shù)作聲明char letter(char c1,char c2) /定義letter函數(shù)float f(float x,float y)/定義f函數(shù) int i(
19、float j,float k) /定義i函數(shù)如果一個函數(shù)被多個函數(shù)所調(diào)用,用這種方法比較好,不必在每個主調(diào)函數(shù)中重復(fù)聲明*4.5 內(nèi)置函數(shù)調(diào)用函數(shù)時需要一定的時間和空間的開銷圖4.5表示函數(shù)調(diào)用的過程:圖4.5C+提供一種提高效率的方法,即在編譯時將所調(diào)用函數(shù)的代碼直接嵌入到主調(diào)函數(shù)中,而不是將流程轉(zhuǎn)出去這種嵌入到主調(diào)函數(shù)中的函數(shù)稱為內(nèi)置函數(shù)(inline function),又稱內(nèi)嵌函數(shù)在有些書中把它譯成內(nèi)聯(lián)函數(shù)指定內(nèi)置函數(shù)的方法很簡單,只需在函數(shù)首行的左端加一個關(guān)鍵字inline即可例4.4 函數(shù)指定為內(nèi)置函數(shù)#include <iostream>using namespac
20、e std;inline int max(int,int, int); /聲明函數(shù),注意左端有inlineint main( )int i=10,j=20,k=30,m; m=max(i,j,k); cout<<max=<<m<<endl; return 0;inline int max(int a,int b,int c) /定義max為內(nèi)置函數(shù)if(b>a) a=b;/求a,b,c中的最大者 if(c>a) a=c; return a;由于在定義函數(shù)時指定它為內(nèi)置函數(shù),因此編譯系統(tǒng)在遇到函數(shù)調(diào)用“max(i,j,k)”時,就用max函數(shù)體的代
21、碼代替“max(i,j,k)”,同時將實參代替形參這樣,程序第6行 “m=max(i,j,k);”就被置換成if (j>i) i=j;if(k>i) i=k;m=i;注意: 可以在聲明函數(shù)和定義函數(shù)時同時寫inline,也可以只在其中一處聲明inline,效果相同,都能按內(nèi)置函數(shù)處理使用內(nèi)置函數(shù)可以節(jié)省運行時間,但卻增加了目標(biāo)程序的長度因此一般只將規(guī)模很小(一般為5個語句以下)而使用頻繁的函數(shù)(如定時采集數(shù)據(jù)的函數(shù))聲明為內(nèi)置函數(shù)內(nèi)置函數(shù)中不能包括復(fù)雜的控制語句,如循環(huán)語句和switch語句應(yīng)當(dāng)說明: 對函數(shù)作inline聲明,只是程序設(shè)計者對編譯系統(tǒng)提出的一個建議,也就是說它是建
22、議性的,而不是指令性的并非一經(jīng)指定為inline,編譯系統(tǒng)就必須這樣做編譯系統(tǒng)會根據(jù)具體情況決定是否這樣做歸納起來,只有那些規(guī)模較小而又被頻繁調(diào)用的簡單函數(shù),才適合于聲明為inline函數(shù)*4.6 函數(shù)的重載在編程時,有時我們要實現(xiàn)的是同一類的功能,只是有些細(xì)節(jié)不同例如希望從3個數(shù)中找出其中的最大者,而每次求最大數(shù)時數(shù)據(jù)的類型不同,可能是3個整數(shù)3個雙精度數(shù)或3個長整數(shù)程序設(shè)計者往往會分別設(shè)計出3個不同名的函數(shù),其函數(shù)原型為:int max1(int a,int b, int c); /求3個整數(shù)中的最大者double max2(double a,double b,double c); /求3
23、個雙精度數(shù)中最大者long max3(long a,long b,long c);/求3個長整數(shù)中的最大者C+允許用同一函數(shù)名定義多個函數(shù),這些函數(shù)的參數(shù)個數(shù)和參數(shù)類型不同這就是函數(shù)的重載(function overloading)即對一個函數(shù)名重新賦予它新的含義,使一個函數(shù)名可以多用對上面求最大數(shù)的問題可以編寫如下的C+程序例4.5 求3個數(shù)中最大的數(shù)(分別考慮整數(shù)雙精度數(shù)長整數(shù)的情況)#include <iostream>using namespace std;int main( )int max(int a,int b,int c); /函數(shù)聲明double max(doub
24、le a,double b,double c); /函數(shù)聲明long max(long a,long b,long c);/函數(shù)聲明 int i1,i2,i3,i; cin>>i1>>i2>>i3; /輸入3個整數(shù) i=max(i1,i2,i3); /求3個整數(shù)中的最大者 cout<<i_max=<<i<<endl; double d1,d2,d3,d; cin>>d1>>d2>>d3; /輸入3個雙精度數(shù) d=max(d1,d2,d3); /求3個雙精度數(shù)中的最大者 cout<&
25、lt;d_max=<<d<<endl; long g1,g2,g3,g; cin>>g1>>g2>>g3; /輸入3個長整數(shù)g=max(g1,g2,g3); /求3個長整數(shù)中的最大者 cout<<g_max=<<g<<endl;int max(int a,int b,int c) /定義求3個整數(shù)中的最大者的函數(shù)if(b>a) a=b; if(c>a) a=c; return a;double max(double a,double b,double c)/定義求3個雙精度數(shù)中的最大者的
26、函數(shù)if(b>a) a=b; if(c>a) a=c; return a;long max(long a,long b,long c) /定義求3個長整數(shù)中的最大者的函數(shù)if(b>a) a=b; if(c>a) a=c; return a;運行情況如下:185-76567 (輸入3個整數(shù))56.87 90.23 -3214.78 (輸入3個實數(shù))67854 - (輸入3個長整數(shù))i_max=567 (輸出3個整數(shù)的最大值)d_max=90.23 (輸出3個雙精度數(shù)的最大值)g_max= (輸出3個長整數(shù)的最大值)上例3個max函數(shù)的函數(shù)體是相同的,其實重載函數(shù)并不要求函
27、數(shù)體相同重載函數(shù)除了允許參數(shù)類型不同以外,還允許參數(shù)的個數(shù)不同例4.6 編寫一個程序,用來求兩個整數(shù)或3個整數(shù)中的最大數(shù)如果輸入兩個整數(shù),程序就輸出這兩個整數(shù)中的最大數(shù),如果輸入3個整數(shù),程序就輸出這3個整數(shù)中的最大數(shù)#include <iostream>using namespace std;int main( )int max(int a,int b,int c); /函數(shù)聲明 int max(int a,int b); /函數(shù)聲明 int a=8,b=-12,c=27; cout<<max(a,b,c)=<<max(a,b,c)<<endl
28、;/輸出3個整數(shù)中的最大者 cout<<max(a,b)=<<max(a,b)<<endl; /輸出兩個整數(shù)中的最大者int max(int a,int b,int c)/此max函數(shù)的作用是求3個整數(shù)中的最大者if(b>a) a=b;if(c>a) a=c; return a;int max(int a,int b)/此max函數(shù)的作用是求兩個整數(shù)中的最大者if(a>b) return a;else return b;運行情況如下:max(a,b,c)=27max(a,b)=8兩次調(diào)用max函數(shù)的參數(shù)個數(shù)不同,系統(tǒng)就根據(jù)參數(shù)的個數(shù)找到與之
29、匹配的函數(shù)并調(diào)用它參數(shù)的個數(shù)和類型可以都不同但不能只有函數(shù)的類型不同而參數(shù)的個數(shù)和類型相同例如:int f(int); /函數(shù)返回值為整型long f(int);/函數(shù)返回值為長整型void f(int);/函數(shù)無返回值在函數(shù)調(diào)用時都是同一形式,如“f(10)”編譯系統(tǒng)無法判別應(yīng)該調(diào)用哪一個函數(shù)重載函數(shù)的參數(shù)個數(shù)參數(shù)類型或參數(shù)順序3者中必須至少有一種不同,函數(shù)返回值類型可以相同也可以不同在使用重載函數(shù)時,同名函數(shù)的功能應(yīng)當(dāng)相同或相近,不要用同一函數(shù)名去實現(xiàn)完全不相干的功能,雖然程序也能運行,但可讀性不好,使人莫名其妙*4.7 函數(shù)模板C+提供了函數(shù)模板(function template)所謂
30、函數(shù)模板,實際上是建立一個通用函數(shù),其函數(shù)類型和形參類型不具體指定,用一個虛擬的類型來代表這個通用函數(shù)就稱為函數(shù)模板凡是函數(shù)體相同的函數(shù)都可以用這個模板來代替,不必定義多個函數(shù),只需在模板中定義一次即可在調(diào)用函數(shù)時系統(tǒng)會根據(jù)實參的類型來取代模板中的虛擬類型,從而實現(xiàn)了不同函數(shù)的功能看下面的例子就清楚了例4.7 將例4.6程序改為通過函數(shù)模板來實現(xiàn)#include <iostream>using namespace std;template<typename T> /模板聲明,其中T為類型參數(shù)T max(T a,T b,T c) /定義一個通用函數(shù),用T作虛擬的類型名if
31、(b>a) a=b; if(c>a) a=c; return a;int main( )int i1=185,i2=-76,i3=567,i; double d1=56.87,d2=90.23,d3=-3214.78,d; long g1=67854,g2=-,g3=,g;i=max(i1,i2,i3); /調(diào)用模板函數(shù),此時T被int取代 d=max(d1,d2,d3); /調(diào)用模板函數(shù),此時T被double取代g=max(g1,g2,g3); /調(diào)用模板函數(shù),此時T被long取代 cout<<i_max=<<i<<endl; cout<
32、<f_max=<<f<<endl; cout<<g_max=<<g<<endl; return 0;運行結(jié)果與例4.5相同為了節(jié)省篇幅,數(shù)據(jù)不用cin語句輸入,而在變量定義時初始化程序第38行是定義模板定義函數(shù)模板的一般形式為 template < typename T> 或 template <class T>通用函數(shù)定義 通用函數(shù)定義在建立函數(shù)模板時,只要將例4.5程序中定義的第一個函數(shù)首部的int改為T即可即用虛擬的類型名T代替具體的數(shù)據(jù)類型在對程序進(jìn)行編譯時,遇到第13行調(diào)用函數(shù)max(i1,i2
33、,i3),編譯系統(tǒng)會將函數(shù)名max與模板max相匹配,將實參的類型取代了函數(shù)模板中的虛擬類型T此時相當(dāng)于已定義了一個函數(shù):int max(int a,int b,int c)if(b>a) a=b; if(c>a) a=c; return a;然后調(diào)用它后面兩行(14,15行)的情況類似類型參數(shù)可以不只一個,可以根據(jù)需要確定個數(shù)如template <class T1,typename T2>可以看到,用函數(shù)模板比函數(shù)重載更方便,程序更簡潔但應(yīng)注意它只適用于函數(shù)的參數(shù)個數(shù)相同而類型不同,且函數(shù)體相同的情況,如果參數(shù)的個數(shù)不同,則不能用函數(shù)模板*4.8 有默認(rèn)參數(shù)的函數(shù)一般
34、情況下,在函數(shù)調(diào)用時形參從實參那里取得值,因此實參的個數(shù)應(yīng)與形參相同有時多次調(diào)用同一函數(shù)時用同樣的實參,C+提供簡單的處理辦法,給形參一個默認(rèn)值,這樣形參就不必一定要從實參取值了如有一函數(shù)聲明float area(float r=6.5);指定r的默認(rèn)值為6.5,如果在調(diào)用此函數(shù)時,確認(rèn)r的值為6.5,則可以不必給出實參的值,如area( );/相當(dāng)于area(6.5);如果不想使形參取此默認(rèn)值,則通過實參另行給出如area(7.5);/形參得到的值為7.5,而不是6.5這種方法比較靈活,可以簡化編程,提高運行效率如果有多個形參,可以使每個形參有一個默認(rèn)值,也可以只對一部分形參指定默認(rèn)值,另一
35、部分形參不指定默認(rèn)值如有一個求圓柱體體積的函數(shù),形參h代表圓柱體的高,r為圓柱體半徑函數(shù)原型如下:float volume(float h,float r=12.5); /只對形參r指定默認(rèn)值12.5函數(shù)調(diào)用可以采用以下形式: volume(45.6); /相當(dāng)于volume(45.6,12.5)volume(34.2,10.4) /h的值為34.2,r的值為10.4實參與形參的結(jié)合是從左至右順序進(jìn)行的因此指定默認(rèn)值的參數(shù)必須放在形參表列中的最右端,否則出錯例如:void f1(float a,int b=0,int c,char d=a); /不正確void f2(float a,int c
36、,int b=0, char d=a); /正確如果調(diào)用上面的f2函數(shù),可以采取下面的形式: f2(3.5, 5, 3, x)/形參的值全部從實參得到f2(3.5, 5, 3) /最后一個形參的值取默認(rèn)值af2(3.5, 5) /最后兩個形參的值取默認(rèn)值,b=0,d=a可以看到,在調(diào)用有默認(rèn)參數(shù)的函數(shù)時,實參的個數(shù)可以與形參的個數(shù)不同,實參未給定的,從形參的默認(rèn)值得到值利用這一特性,可以使函數(shù)的使用更加靈活例如例4.7求2個數(shù)或3個數(shù)中的最大數(shù)也可以不用重載函數(shù),而改用帶有默認(rèn)參數(shù)的函數(shù)例4.8 求2個或3個正整數(shù)中的最大數(shù),用帶有默認(rèn)參數(shù)的函數(shù)實現(xiàn)#include <iostream&
37、gt;using namespace std;int main( )int max(int a, int b, int c=0);/函數(shù)聲明,形參c有默認(rèn)值int a,b,c; cin>>a>>b>>c; cout<<max(a,b,c)=<<max(a,b,c)<<endl;/輸出3個數(shù)中的最大者 cout<<max(a,b)=<<max(a,b)<<endl; /輸出2個數(shù)中的最大者 return 0;int max(int a,int b,int c) /函數(shù)定義if(b>a
38、) a=b; if(c>a) a=c; return a;運行情況如下:14 -56 135max(a,b,c)=135max(a,b)=14在使用帶有默認(rèn)參數(shù)的函數(shù)時有兩點要注意:(1) 如果函數(shù)的定義在函數(shù)調(diào)用之前,則應(yīng)在函數(shù)定義中給出默認(rèn)值如果函數(shù)的定義在函數(shù)調(diào)用之后,則在函數(shù)調(diào)用之前需要有函數(shù)聲明,此時必須在函數(shù)聲明中給出默認(rèn)值,在函數(shù)定義時可以不給出默認(rèn)值(如例4.8)(2) 一個函數(shù)不能既作為重載函數(shù),又作為有默認(rèn)參數(shù)的函數(shù)因為當(dāng)調(diào)用函數(shù)時如果少寫一個參數(shù),系統(tǒng)無法判定是利用重載函數(shù)還是利用默認(rèn)參數(shù)的函數(shù),出現(xiàn)二義性,系統(tǒng)無法執(zhí)行4.9 函數(shù)的嵌套調(diào)用C+不允許對函數(shù)作嵌套定
39、義,也就是說在一個函數(shù)中不能完整地包含另一個函數(shù)在一個程序中每一個函數(shù)的定義都是互相平行和獨立的雖然C+不能嵌套定義函數(shù),但可以嵌套調(diào)用函數(shù),也就是說,在調(diào)用一個函數(shù)的過程中,又調(diào)用另一個函數(shù)見圖4.6圖4.6在程序中實現(xiàn)函數(shù)嵌套調(diào)用時,需要注意的是: 在調(diào)用函數(shù)之前,需要對每一個被調(diào)用的函數(shù)作聲明(除非定義在前,調(diào)用在后)例4.9 用弦截法求方程f(x)=x3-5x2+16x-80=0的根這是一個數(shù)值求解問題,需要先分析用弦截法求根的算法根據(jù)數(shù)學(xué)知識,可以列出以下的解題步驟: (1) 取兩個不同點x1,x2,如果f(x1)和f(x2)符號相反,則(x1,x2)區(qū)間內(nèi)必有一個根如果f(x1)與
40、f(x2)同符號,則應(yīng)改變x1,x2,直到f(x1), f(x2)異號為止注意x1x2的值不應(yīng)差太大,以保證(x1,x2)區(qū)間內(nèi)只有一個根(2) 連接(x1, f(x1)和(x2, f(x2)兩點,此線(即弦)交x軸于x,見圖4.7圖4.7x點坐標(biāo)可用下式求出:x=x1·f(x2)-x2·f(x1) f(x2)-f(x1)再從x求出f(x)(3) 若f(x)與f(x1)同符號,則根必在(x, x2)區(qū)間內(nèi),此時將x作為新的x1如果f(x)與f(x2)同符號,則表示根在( x1,x)區(qū)間內(nèi),將x作為新的x2(4) 重復(fù)步驟 (2) 和 (3), 直到 |f(x)|<為止
41、, 為一個很小的正數(shù), 例如10-6此時認(rèn)為 f(x)0這就是弦截法的算法,在程序中分別用以下幾個函數(shù)來實現(xiàn)以上有關(guān)部分功能:(1) 用函數(shù)f(x)代表x的函數(shù):x3-5x2+16x-80(2) 用函數(shù)xpoint (x1,x2)來求(x1,f(x1)和(x2,f(x2)的連線與x軸的交點x的坐標(biāo)(3) 用函數(shù)root(x1,x2)來求(x1,x2)區(qū)間的那個實根顯然,執(zhí)行root函數(shù)的過程中要用到xpoint函數(shù),而執(zhí)行xpoint函數(shù)的過程中要用到f函數(shù)根據(jù)以上算法,可以編寫出下面的程序:#include <iostream>#include <iomanip>#i
42、nclude <cmath>using namespace std;double f(double); /函數(shù)聲明 double xpoint(double, double); /函數(shù)聲明double root(double, double); /函數(shù)聲明int main( ) double x1,x2,f1,f2,x;do cout<<input x1,x2:;cin>>x1>>x2;f1=f(x1);f2=f(x2); while(f1*f2>=0); x=root(x1,x2); cout<<setiosflags(ios
43、fixed)<<setprecision(7); /指定輸出7位小數(shù) cout<<A root of equation is <<x<<endl; return 0;double f(double x) /定義f函數(shù),以實現(xiàn)f(x)double y; y=x*x*x-5*x*x+16*x-80; return y;double xpoint(double x1, double x2) /定義xpoint函數(shù),求出弦與x軸交點double y; y=(x1*f(x2)-x2*f(x1)/(f(x2)-f(x1); /在xpoint函數(shù)中調(diào)用f函數(shù)
44、return y;double root(double x1, double x2) /定義root函數(shù),求近似根double x,y,y1; y1=f(x1); do x=xpoint(x1,x2); /在root函數(shù)中調(diào)用xpoint函數(shù)y=f(x); /在root函數(shù)中調(diào)用f函數(shù)if (y*y1>0) y1=y; x1=x; elsex2=x; while(fabs(y)>=0.00001); return x;運行情況如下:input x1,x2:2.5 6.7A root of equation is 5.對程序的說明:(1) 在定義函數(shù)時,函數(shù)名為f,xpoint和ro
45、ot的3個函數(shù)是互相獨立的,并不互相從屬這3個函數(shù)均定為雙精度型(2) 3個函數(shù)的定義均出現(xiàn)在main函數(shù)之后,因此在main函數(shù)的前面對這3個函數(shù)作聲明習(xí)慣上把本程序中用到的所有函數(shù)集中放在最前面聲明 (3) 程序從main函數(shù)開始執(zhí)行函數(shù)的嵌套調(diào)用見圖4.8圖4.8(4) 在root函數(shù)中要用到求絕對值的函數(shù)fabs,它是對雙精度數(shù)求絕對值的系統(tǒng)函數(shù)它屬于數(shù)學(xué)函數(shù)庫,故在文件開頭用#include <cmath>把有關(guān)的頭文件包含進(jìn)來 4.10 函數(shù)的遞歸調(diào)用在調(diào)用一個函數(shù)的過程中又出現(xiàn)直接或間接地調(diào)用該函數(shù)本身,稱為函數(shù)的遞歸(recursive)調(diào)用C+允許函數(shù)的遞歸調(diào)用例
46、如:int f(int x)int y,z;z=f(y); /在調(diào)用函數(shù)f的過程中,又要調(diào)用f函數(shù)return (2*z);以上是直接調(diào)用本函數(shù),見圖4.9圖4.10表示的是間接調(diào)用本函數(shù)在調(diào)用f1函數(shù)過程中要調(diào)用f2函數(shù),而在調(diào)用f2函數(shù)過程中又要調(diào)用f1函數(shù) 圖4.9圖4.10從圖上可以看到,這兩種遞歸調(diào)用都是無終止的自身調(diào)用顯然,程序中不應(yīng)出現(xiàn)這種無終止的遞歸調(diào)用,而只應(yīng)出現(xiàn)有限次數(shù)的有終止的遞歸調(diào)用,這可以用if語句來控制,只有在某一條件成立時才繼續(xù)執(zhí)行遞歸調(diào)用,否則就不再繼續(xù)包含遞歸調(diào)用的函數(shù)稱為遞歸函數(shù)例4.10 有5個人坐在一起,問第5個人多少歲?他說比第4個人大兩歲問第4個人歲
47、數(shù),他說比第3個人大兩歲問第3個人,又說比第2個人大兩歲問第2個人,說比第1個人大兩歲最后問第1個人,他說是10歲請問第5個人多大?每一個人的年齡都比其前1個人的年齡大兩歲即age(5)=age(4)+2age(4)=age(3)+2age(3)=age(2)+2age(2)=age(1)+2age(1)=10可以用式子表述如下:age(n)=10 (n=1)age(n)=age(n-1)+2 (n>1)可以看到,當(dāng)n>1時,求第n個人的年齡的公式是相同的因此可以用一個函數(shù)表示上述關(guān)系圖4.11表示求第5個人年齡的過程圖4.11可以寫出以下C+程序,其中的age函數(shù)用來實現(xiàn)上述遞歸
48、過程#include <iostream>using namespace std;int age(int);/函數(shù)聲明int main( )/主函數(shù) cout<<age(5)<<endl;return 0; int age(int n)/求年齡的遞歸函數(shù)int c; /用c作為存放年齡的變量 if(n=1) c=10; /當(dāng)n=1時,年齡為10 else c=age(n-1)+2; /當(dāng)n>1時,此人年齡是他前一個人的年齡加2 return c; /將年齡值帶回主函數(shù)運行結(jié)果如下:18函數(shù)調(diào)用過程如圖4.12所示圖4.12例4.11 用遞歸方法求n!求
49、n!可以用遞推方法,即從1開始,乘2,再乘3一直乘到n求n!也可以用遞歸方法,即5!=4!×5,而4!=3!×4,1!=1可用下面的遞歸公式表示: n!=1(n=0,1)n·(n-1)!(n>1)有了例4.10的基礎(chǔ),很容易寫出本題的程序:#include <iostream>using namespace std;long fac(int);/函數(shù)聲明int main( ) int n;/n為需要求階乘的整數(shù)long y; /y為存放n!的變量cout<<please input an integer :; /輸入的提示cin>
50、;>n; /輸入n y=fac(n);/調(diào)用fac函數(shù)以求n! cout<<n<<!=<<y<<endl; /輸出n!的值 return 0; long fac(int n) /遞歸函數(shù)long f; if(n<0) cout<<n<0,data error!<<endl; /如果輸入負(fù)數(shù),報錯并以-1作為返回值f=-1; else if (n=0|n=1) f=1; /0!和1!的值為1else f=fac(n-1)*n;/n>1時,進(jìn)行遞歸調(diào)用 return f;/將f的值作為函數(shù)值返回運行情況
51、如下:please input an integer:1010!=許多問題既可以用遞歸方法來處理,也可以用非遞歸方法來處理在實現(xiàn)遞歸時,在時間和空間上的開銷比較大,但符合人們的思路,程序容易理解4.11 局部變量和全局變量 4.11.1 局部變量在一個函數(shù)內(nèi)部定義的變量是內(nèi)部變量,它只在本函數(shù)范圍內(nèi)有效,也就是說只有在本函數(shù)內(nèi)才能使用它們,在此函數(shù)以外是不能使用這些變量的同樣,在復(fù)合語句中定義的變量只在本復(fù)合語句范圍內(nèi)有效這稱為局部變量(local variable)如float f1(int a) /函數(shù)f1int b,c; bc有效a有效char f2(int x, int y) /函數(shù)f
52、2 int i,j; ij有效xy有效int main( ) /主函數(shù)int m,n;int p,q; pq在復(fù)合語句中有效mn有效說明:(1) 主函數(shù)main中定義的變量(m,n)也只在主函數(shù)中有效,不會因為在主函數(shù)中定義而在整個文件或程序中有效主函數(shù)也不能使用其他函數(shù)中定義的變量(2) 不同函數(shù)中可以使用同名的變量,它們代表不同的對象,互不干擾例如,在f1函數(shù)中定義了變量b和c,倘若在f2函數(shù)中也定義變量b和c,它們在內(nèi)存中占不同的單元,不會混淆(3) 可以在一個函數(shù)內(nèi)的復(fù)合語句中定義變量,這些變量只在本復(fù)合語句中有效,這種復(fù)合語句也稱為分程序或程序塊(4) 形式參數(shù)也是局部變量例如f1函
53、數(shù)中的形參a也只在f1函數(shù)中有效其他函數(shù)不能調(diào)用(5) 在函數(shù)聲明中出現(xiàn)的參數(shù)名,其作用范圍只在本行的括號內(nèi)實際上,編譯系統(tǒng)對函數(shù)聲明中的變量名是忽略的,即使在調(diào)用函數(shù)時也沒有為它們分配存儲單元例如int max(int a,int b);/函數(shù)聲明中出現(xiàn)abint max(int x,int y) /函數(shù)定義,形參是xy cout<<x<<y<<endl; /合法,xy在函數(shù)體中有效cout<<a<<b<<endl; /非法,ab在函數(shù)體中無效編譯時認(rèn)為max函數(shù)體中的a和b未經(jīng)定義4.11.2 全局變量前面已介紹,程序
54、的編譯單位是源程序文件,一個源文件可以包含一個或若干個函數(shù)在函數(shù)內(nèi)定義的變量是局部變量,而在函數(shù)之外定義的變量是外部變量,稱為全局變量(global variable,也稱全程變量)全局變量的有效范圍為從定義變量的位置開始到本源文件結(jié)束如int p=1,q=5;/全局變量全局變量c1c2的作用范圍 float f1(a)/定義函數(shù)f1int a;int b,c;char c1,c2; /全局變量全局變量pq的作用范圍char f2 (int x, int y) /定義函數(shù)f2int i,j;main ( )/主函數(shù)int m,n;pqc1c2都是全局變量,但它們的作用范圍不同,在main函數(shù)和
55、f2函數(shù)中可以使用全局變量pqc1c2,但在函數(shù)f1中只能使用全局變量pq,而不能使用c1和c2在一個函數(shù)中既可以使用本函數(shù)中的局部變量,又可以使用有效的全局變量說明:(1) 設(shè)全局變量的作用是增加函數(shù)間數(shù)據(jù)聯(lián)系的渠道(2) 建議不在必要時不要使用全局變量,因為: 全局變量在程序的全部執(zhí)行過程中都占用存儲單元,而不是僅在需要時才開辟單元 它使函數(shù)的通用性降低了,因為在執(zhí)行函數(shù)時要受到外部變量的影響如果將一個函數(shù)移到另一個文件中,還要將有關(guān)的外部變量及其值一起移過去但若該外部變量與其他文件的變量同名,就會出現(xiàn)問題,降低了程序的可靠性和通用性在程序設(shè)計中,在劃分模塊時要求模塊的內(nèi)聚性強(qiáng)與其他模塊的耦合性弱即模塊的功能要單一(不要把許多互不相干的功能放到一個模塊中),與其他模塊的相互影響要盡量少,而
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 人教版品德與社會五年級上冊全冊教案
- 開發(fā)耐低溫材料保障極地工程安全
- 現(xiàn)代工程圖學(xué)習(xí)題集答案-第三版-主編楊裕根第3章
- 高一化學(xué)達(dá)標(biāo)訓(xùn)練:第一單元化學(xué)反應(yīng)速率與反應(yīng)限度
- 2024屆西安市航空六一八中學(xué)高考化學(xué)四模試卷含解析
- 2024高中語文第一單元第2課裝在套子里的人提升訓(xùn)練含解析新人教版必修5
- 2024高考地理一輪復(fù)習(xí)第二章地球上的大氣第三講氣壓帶和風(fēng)帶學(xué)案
- 2024高考化學(xué)一輪復(fù)習(xí)第九章有機(jī)化合物第一講甲烷乙烯苯規(guī)范演練含解析新人教版
- 貸款違約調(diào)解協(xié)議書
- 大數(shù)據(jù)時代語言學(xué)
- 中華人民共和國能源法
- 礦山智能化監(jiān)控系統(tǒng)
- 五年級口算題卡每天100題帶答案
- Unit 3 Family Matters Developing Ideas Writing about a Family Memory 教學(xué)設(shè)計-2024-2025學(xué)年高一上學(xué)期英語外研版(2019)必修第一冊
- 工程量清單及招標(biāo)控制價編制工作方案
- 商業(yè)承兌匯票貼現(xiàn)協(xié)議
- 普工附有答案
- 《烏魯木齊市國土空間總體規(guī)劃(2021-2035年)》
- 2024年中國租賃業(yè)調(diào)查報告-畢馬威-202407
- 中俄東線天然氣管道工程(永清-上海)環(huán)境影響報告書
- 2024年長沙市中考數(shù)學(xué)真題試卷及答案
評論
0/150
提交評論