




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第四章過程抽象--函數第1頁本章內容子程序函數帶缺省值形式參數變量局部性遞歸函數函數名重載內聯函數條件編譯第2頁子程序子程序是命了名一段程序代碼,它通常完成一個獨立(子)功效。子程序除了能夠起到節約程序代碼量作用外,它還有一個非常主要作用:過程抽象,即,一個子程序代表一個功效。在程序其它地方經過子程序名字來使用(調用)子程序,而無須關心它們是怎樣實現。第3頁函數函數是C++提供用于實現子程序語言成份。函數定義:<返回值類型><函數名>(<形式參數表>)<函數體>形參說明格式為:<類型><形參名><函數體>為一個<復合語句>,用于實現對應函數功效。函數體內能夠包含return語句,當函數體執行到return語句時,函數馬上返回到調用者。return語句格式:return<表示式>;return;注意:在函數體中不能用goto語句轉出函數體。第4頁函數例子intfactorial(intn)//求n階乘{ inti,f=1; for(i=2;i<=n;i++)f*=i; returnf;}第5頁voidHi(){cout<<“Hi”<<endl;return;//可省略}第6頁例1關于C++函數,以下表述正確是A每個函數都有一個函數名B每個函數都有一個返回值C每個函數都有一個或多個參數D每個函數都用return語句結束運行第7頁函數調用
對于定義一個函數,必須要調用它,它函數體才會執行。函數調用格式以下:<函數名>(<實在參數表>)<實在參數表>由零個、一個或多個表示式組成(逗號分割),其個數和類型應與對應函數形參相同。注意:不能用goto語句從函數外轉入函數體第8頁函數調用例子......intmain(){ intx; cout<<"請輸入一個正整數:"; cin>>x; cout<<"Factorialof"<<x<<"is" <<factorial(x)//調用階乘函數 <<endl; return0;}第9頁函數調用執行過程計算實參值(對于多個實參,C++沒有要求計算次序);把實參分別傳遞給被調用函數形參;執行函數體;函數體中執行return語句返回函數調用點,調用點取得返回值(假如有返回值)并執行調用之后操作。第10頁函數申明程序中調用全部函數都要有定義。假如函數定義在其它文件(如:C++標準庫)中或定義在根源文件中使用點之后,則在調用前需要對被調用函數進行申明。函數申明格式以下:<返回值類型><函數名>(<形式參數表>);//函數原型extern<返回值類型><函數名>(<形式參數表>);在函數申明中,<形式參數表>中能夠只列出形參類型而不寫形參名。第11頁例2關于函數調用,以下表述正確是A調用函數時必須給出實參B必須在表示式中調用函數C函數必須先有定義才能調用D函數不能自己調用自己第12頁例:用函數實現求小于n全部素數。#include<iostream>usingnamespacestd;boolis_prime(intn);//函數申明voidprint_prime(intn,intcount);//函數申明intmain(){ inti,n,count=1; cout<<"請輸入一個正整數:" cin>>n;//從鍵盤輸入一個正整數 if(n<2)return-1; cout<<2<<",";//輸出第一個素數 for(i=3;i<n;i+=2) { if(is_prime(i)) { count++; print_prime(i,count); } }第13頁 cout<<endl; return0;}boolis_prime(intn){ inti,j; for(i=2,j=n;i<=j;i++) if(n%i==0)returnfalse; returntrue;}voidprint_prime(intn,intcount){ cout<<n<<','; if(count%6==0)cout<<endl;}第14頁函數參數傳遞C++提供了兩種參數傳遞機制:值傳遞和引用傳遞。C++默認參數傳遞方式是值傳遞。值傳遞是指在函數調用時,采取類似賦值操作形式把實參傳給形參。函數執行過程中,經過形參取得實參值,函數體中對形參值改變不會影響對應實參值。假如有多個實參要傳給函數,而每個實參都是表示式,這時,C++并沒有要求這些實參表示式計算次序,實際計算次序由詳細編譯程序來決定。第15頁值參數傳遞例子#include<iostream>usingnamespacestd;doubleplus3(doublen);intmain(){ doublem=3.0; cout<<m<<plus3(m)<<m<<endl; return0;}第16頁doubleplus3(doublen){ n+=3;returnn;}第17頁執行main時,產生一個變量n: m:3.0調用power函數時,又產生一個變量m,然后用n對它初始化: m:3.0n:3.0函數plus3中賦值操作結束后(函數返回前): m:3.0n:6.0函數power返回后: m:3.0n:6.0第18頁參數默認值在C++中允許在定義或申明函數時,為函數一些參數指定默認值。假如調用這些函數時沒有提供對應實參,則對應形參采取指定默認值,不然對應形參采取調用者提供實參值。比如,對于下面函數申明:voidprint(intvalue,intbase=10);下面調用:print(28,10);//28傳給value;10傳給baseprint(32,2);//32傳給value;2傳給base第19頁在指定函數參數默認值時,應注意下面幾點:有默認值形參應處于形參表右部。比如:voidf(inta,intb=1,intc=0);//OKvoidf(inta,intb=1,intc);//Error
對參數默認值指定只在函數申明處有意義。在不一樣源文件中,對同一個函數申明能夠對它同一個參數指定不一樣默認值;在同一個源文件中,對同一個函數申明只能對它每一個參數指定一次默認值。
第20頁若函數原型說明為:intf(chara,char*b=NULL,doublec=0.0);則以下調用函數f選項中,語法錯誤是f(99)f(‘A’,4.5)f(‘A’,”123”)f((char)65,“123”)第21頁變量局部性在C++中,依據變量定義位置,把變量分成:全局變量和局部變量。全局變量是指定義在函數外部變量,它們普通能被程序中全部函數使用(靜態全局變量除外)。局部變量是指在復合語句中定義變量,它們只能在定義它們復合語句(包含內層復合語句)中使用。第22頁全局變量和局部變量例子intx=0;//全局變量voidf(){ inty=0;//局部變量 x++;//OK y++;//OK}voidg(){ x++;//OK y++;//Error}intmain(){ f();g(); x++;//OK y++;//Error return0;}第23頁例3關于變量表述,錯誤是A在一個函數中能夠訪問定義在函數外變量B在一個函數中能夠訪問定義在另一個函數中變量C在一個函數中能夠訪問定義在另一個程序文件中變量D在一個函數中能夠訪問定義在同一函數中變量第24頁問題函數能夠訪問其它程序文件中變量前提:在定義變量文件中,該變量定義在函數外,而且沒有加static修飾;在訪問該變量文件中有對應extern申明第25頁變量生存期(存放分配)把程序運行時一個變量占有內存空間時間段稱為該變量生存期。C++把變量生存期分為:靜態:內存空間從程序開始執行時就進行分配,直到程序結束才收回它們空間。全局變量含有靜態生存期。自動:內存空間在程序執行到定義它們復合語句(包含函數體)時才分配,當定義它們復合語句執行結束時,它們空間將被收回。局部變量和函數參數普通含有自動生存期。動態:內存空間用new操作分配、用delete操作收回。動態變量含有動態生存期。
第26頁存放類修飾符在定義局部變量時,能夠為它們加上存放類修飾符來指出它們生存期。auto:局部變量含有自動生存期。局部變量默認存放類為auto。static:局部變量含有靜態生存期,只在函數第一次調用時進行初始化,以后調用中不再進行初始化,它值為上一次函數調用結束時值。register:局部變量含有自動生存期,由編譯程序依據CPU存放器使用情況來決定是否存放在存放器中。第27頁voidf(){intx=0;staticinty=1;registerintz=0;x++;y++;z++;cout<<x<<y<<z<<endl;}第一次調用f時,輸出:第二次調用f時,輸出:121131第28頁C++程序多模塊結構一個C++程序由一些全局函數(區分于類定義中組員函數)、全局常量、全局變量/對象以及類定義組成,其中必須有且僅有一個名字為main全局函數。函數內部能夠包含形參、局部常量、局部變量/對象定義以及語句。模塊是一個可單獨編譯程序單位,它用來對程序邏輯單位進行分組。一個模塊普通由包含兩個部分:接口(.h文件):給出在本模塊中定義、提供給其它模塊使用一些程序實體(如:函數、全局變量等)申明;實現(.cpp文件):模塊實現給出了模塊中程序實體定義。第29頁//file1.hexternintx;//全局變量x申明externdoubley;//全局變量y申明intf();//全局函數f申明//file1.cppintx=1;//全局變量x定義doubley=2.0;//全局變量y定義intf()//全局函數f定義{ intm;//局部變量m定義 ...... m+=x;//語句 ...... returnm;}第30頁//file2.hvoidg();//全局函數g申明//file2.cpp#include"file1.h"http://把文件file1.h中內容包含進來voidg()//全局函數g定義{ doublez;//局部變量z定義 ...... z=y+10;//語句 ......}第31頁//main.cpp#include"file1.h"http://把文件file1.h中內容包含進來#include"file2.h"http://把文件file2.h中內容包含進來intmain()//全局函數main定義{ doubler;//局部變量r定義 ...... r=x+y*f();//語句 ...... g();//語句 ......}第32頁標識符作用域一個定義了標識符有效范圍(能被訪問程序段)稱為該標識符作用域。C++把標識符作用域分成若干類,其中包含:局部作用域全局作用域文件作用域函數作用域函數原型作用域類作用域名空間作用域第33頁局部作用域在函數定義或復合語句中、從標識符定義點開始到函數定義或復合語句結束之間程序段。C++中局部常量名、局部變量名/對象名以及函數形參名含有局部作用域。假如在一個標識符局部作用域中包含內層復合語句,而且在該內層復合語句中定義了一個同名不一樣實體,則外層定義標識符作用域應該是從其潛在作用域中扣除內層同名標識符作用域之后所得到作用域。第34頁voidf(){ ...x...//Error intx;//外層x定義 ...x...//外層x while(...x...)//外層x { ...x...//外層x doublex;//內層x定義 ...x...//內層x } ...x...//外層x}第35頁全局作用域全局變量名/對象名、全局函數名和全局類名作用域普通含有全局作用域,它們在整個程序中可用。假如在某個局部作用域中定義了與某個全局標識符同名標識符,則該全局標識符作用域應扣掉與之同名局部標識符作用域。在局部標識符作用域中若要使用與其同名全局標識符,則需要用全局域選擇符(::)對全局標識符進行修飾(受限)。把全局標識符申明放在某個.h文件中,在需要使用這些全局標識符源文件中用#include編譯預處理命令把申明文件包含進來。
第36頁doublex;//外層x定義voidf(){ intx;//內層x定義 ...x...//內層x ...::x...//外層x}第37頁文件作用域在全局標識符定義中加上static修飾符,則該全局標識符就成了含有文件作用域標識符,它們只能在定義它們源文件中使用。C++中關鍵詞static有兩個不一樣含義。在局部變量定義中,static修飾符用于指定局部變量采取靜態存放分配;而在全局標識符定義中,static修飾符用于把全局標識符作用域改變為文件作用域。
普通情況下,含有全局作用域標識符主要用于標識被程序各個模塊共享程序實體,而含有文件作用域標識符用于標識在一個模塊內部共享程序實體。第38頁//file1.cppstaticinty;//文件作用域staticvoidf()//文件作用域{......}//file2.cppexterninty;externvoidf();voidg(){...y...//Errorf();//Error}第39頁函數作用域語句標號是唯一含有函數作用域標識符,它們在定義它們函數體中任何地方都能夠訪問。函數作用域與局部作用域區分是:函數作用域包含整個函數,而局部作用域是從定義點開始到函數定義或復合語句結束。在函數體中,一個語句標號只能定義一次,即使是在內層復合語句中,也不能再定義與外層相同語句標號。第40頁voidf(){ ...... gotoL;//OK ...... L:... ...... gotoL;//OK ......}voidg(){ ...... gotoL;//Error ......}第41頁名空間作用域對于一個多文件組成程序,有時見面臨一個問題:在一個源文件中要用到兩個分別在另外兩個源文件中定義不一樣全局程序實體(如:全局函數),而這兩個全局程序實體名字相同。C++提供了名空間(namespace)設施來處理上述名沖突問題。在一個名空間中定義全局標識符,其作用域為該名空間。當在一個名空間外部需要使用該名空間中定義全局標識符時,可用該名空間名字來修飾或受限。第42頁namespaceA{ intx=1; voidf() {...... }}namespaceB{ intx=0; voidf() {...... }}...A::x...//A中xA::f();//A中f...B::x...//B中xB::f();//B中fusingnamespaceA;...x...//A中xf();//A中f...B::x...//B中xB::f();//B中fusingA::f;...A::x...//A中x
f();//A中f...B::x...//B中xB::f();//B中f第43頁遞歸函數函數調用是能夠嵌套。假如一個函數在其函數體中直接或間接地調用了自己,則該函數稱為遞歸函數。
第44頁直接遞歸voidf(){..........f()..........}間接遞歸externvoidg();voidf(){..........g()..........}voidg(){.........f().........}第45頁遞歸函數作用在程序設計中經常需要實現重復性操作。循環為實現重復操作提供了一個路徑。實現重復操作另一個路徑是采取遞歸函數。“分而治之”(DivideandConquer)設計方法:把一個問題分解成若干個子問題,而每個子問題性質與原問題相同,只是在規模上比原問題要小。每個子問題求解過程能夠采取與原問題相同方式來進行。遞歸函數為上述設計方法提供了一個自然、簡練實現機制第46頁遞歸函數執行過程//用遞歸函數求n!
intf(intn){ if(n==0) return1; else returnn*f(n-1);}第47頁遞歸條件和結束條件在定義遞歸函數時,一定要對兩種情況給出描述:遞歸條件。指出何時進行遞歸調用,它描述了問題求解普通情況,包含:分解和綜合過程。結束條件。指出何時不需遞歸調用,它描述了問題求解特殊情況或基本情況第48頁遞歸與循環選擇對于一些遞歸定義問題,用遞歸函數來處理會顯得比較自然和簡練,而用循環來處理這么問題,有時會很復雜,不易設計和了解。在實現數據操作上,它們有一點不一樣:循環是在同一組變量上進行重復操作(循環經常又稱為迭代)遞歸則是在不一樣變量組(屬于遞歸函數不一樣實例)上進行重復操作。遞歸表示重復操作是經過函數調用來實現,而函數調用是需要開銷第49頁函數名重載對于一些功效相同、參數類型或個數不一樣函數,有時給它們取相同名字會帶來使用上方便。比如,把下面函數:voidprint_int(inti){......}voidprint_double(doubled){......}voidprint_char(charc){......}voidprint_A(Aa){......}//A為自定義類型定義為:voidprint(inti){......}voidprint(doubled){......}voidprint(charc){......}voidprint(Aa){......}上述函數定義形式稱為函數名重載。第50頁例假如已經有以下函數定義,intf(intk,intm=0,doubled=0.0)能否重載以下函數?intf(int,int);f(3,0)不能重載,要看調用時實際效果。調用時無法區分這兩個函數。第51頁應該從調用角度去了解:重載函數必須在參數個數與類型上不一樣而不應該從定義角度了解所以,應該在去掉全部默認參數前提下,在參數個數與類型上不一樣第52頁對重載函數調用綁定確定一個對重載函數調用對應著哪一個重載函數定義過程稱為綁定(binding,又稱定聯、聯編、捆綁)。在編譯時刻由編譯程序依據實參加形參匹配情況來決定。從形參個數與實參個數相同重載函數中按下面規則選擇一個:p106準確匹配提升匹配標準轉換匹配自定義轉換匹配匹配失敗第53頁處理小函數低效問題因為函數調用是需要開銷,尤其是對一些小函數頻繁調用將使程序效率有很大降低。C++提供了兩種處理上述問題方法:宏定義內聯函數第54頁宏定義宏定義用#define來實現,它是C++一個編譯預處理命令。在C++中,宏定義有4種格式:#define凵<宏名>凵<文字串>#define凵<宏名>(<參數表>)凵<文字串>#define凵<宏名>#undef凵<宏名>上面格式2宏定義能夠實現類似函數功效,比如:#define凵max(a,b)凵(((a)>(b))?(a):(b))cout<<max(x,y);第55頁宏定義只是進行簡單文字替換#defineT(x,y)x*y/4(05秋)則表示式T(3+4,4+4)值為?3+4*4+4/4=20第56頁宏定義不足處有時會出現重復計算。比如:max(x+1,y*2)將被替換成:(((x+1)>(y*2))?(x+1):(y*2))不進行參數類型檢驗和轉換。
不利于一些工具對程序處理。
第57頁內聯函數內聯函數是指在函數定義中,能夠在函數返回類型之前加上一個關鍵詞inline,比如:inlineintmax(inta,intb){ returna>b?a:b;}內聯函數作用是提議編譯程序把該函數函數體展開到調用點。內聯函數形式上屬于函數,它遵照函數一些要求,如:參數類型檢驗與轉換。使用內聯函數時應注意以下幾點:編譯程序對內聯函數限制。內聯函數名含有文件作用域。第58頁編譯預處理命令C++程序中能夠寫一些供編譯程序使用命令:編譯預處理命令,這些命令不是C++程序所要完成功效,而是用于對編譯過程給出指導,其功效由編譯預處理系統來完成。主要有:文件包含命
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 小學生紀律衛生管理規范
- 2025西安市職工大學輔導員考試試題及答案
- 2025燕山大學里仁學院輔導員考試試題及答案
- 2025蘇州高博軟件技術職業學院輔導員考試試題及答案
- 2025福建中醫藥大學輔導員考試試題及答案
- 室內設計霸氣
- 生活標志設計原理與應用
- 四川北牧南江黃羊集團有限公司招聘筆試題庫2025
- 四川自貢市大安區區屬國有企業招聘筆試題庫2025
- 醫院建筑設計案例分析
- 合伙款退還協議書
- 2025年法律法規考試高分攻略試題及答案
- 2025年統計學專業期末考試題庫-抽樣調查方法應用案例分析試題
- 2025陜西中考:歷史必背知識點
- 2025年下半年貴州烏江水電開發限責任公司大學畢業生招聘若干人易考易錯模擬試題(共500題)試卷后附參考答案
- 2025屆百師聯盟高三下學期二輪復習聯考(三)化學試題(含答案)
- 2025年內蒙古包頭市中考數學一模試卷
- 2025年浙江東陽市九年級中考語文3月模擬試卷(附答案解析)
- 陪玩俱樂部合同協議模板
- 2025年上海市徐匯區初三二模語文試卷(含答案)
- 腦梗死的介入治療
評論
0/150
提交評論