函數(shù)和編譯預處理第5章_第1頁
函數(shù)和編譯預處理第5章_第2頁
函數(shù)和編譯預處理第5章_第3頁
函數(shù)和編譯預處理第5章_第4頁
函數(shù)和編譯預處理第5章_第5頁
已閱讀5頁,還剩87頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

函數(shù)和編譯預處理第5章引言函數(shù)的定義和調(diào)用函數(shù)的原型說明與值調(diào)用函數(shù)的嵌套和遞歸調(diào)用作用域和存儲類內(nèi)聯(lián)函數(shù)具有缺省參數(shù)值的函數(shù)函數(shù)重載編譯預處理程序的多文件組織本章學習要求掌握函數(shù)定義的格式;掌握函數(shù)原形的概念及其與頭文件的關系;掌握兩種形式的函數(shù)調(diào)用(表達式中的函數(shù)調(diào)用和語句中的函數(shù)調(diào)用);掌握函數(shù)調(diào)用過程中參數(shù)傳遞的原理;掌握函數(shù)重載的方法;掌握保留字inline的含義與使用;了解函數(shù)和變量的作用域與生存期;掌握和應用宏定義、條件編譯、文件包含。引言隨著模擬對象的復雜性增加,程序?qū)兊迷絹碓綇碗s和冗長。在編寫一個較大的程序時,為了便于管理,可以采用一些較好的編程策略,常用的方法是按功能或操作將程序分割成一些具有特定功能的、相對獨立的且便于管理和閱讀的小模塊。本章主要介紹這種分割工具之一:函數(shù),包括函數(shù)的定義、函數(shù)的調(diào)用、參數(shù)的傳遞方法、內(nèi)聯(lián)函數(shù)、函數(shù)的重載、變量的作用域等,另外簡要介紹編譯預處理以及程序多文件組織的編譯和連接方法。

函數(shù)的定義和調(diào)用函數(shù)概述

函數(shù)定義

函數(shù)調(diào)用

5.1函數(shù)概述C++中的函數(shù)就是具有特定功能的模塊。函數(shù)是構成C++程序的基本單位,C++程序的運行都是由主函數(shù)(main())開始,然后通過一系列函數(shù)調(diào)用來實現(xiàn)各種功能。從用戶角度看,函數(shù)包括用戶自定義函數(shù)和系統(tǒng)庫函數(shù)。從函數(shù)的形式來看,函數(shù)可以分為無參函數(shù)、有參函數(shù)、無返回值函數(shù)和有返回值函數(shù)等。除了main()函數(shù)以外,一個函數(shù)既可以被其它函數(shù)調(diào)用,也可以調(diào)用其它函數(shù)。圖5-l反映了函數(shù)的層次組織結(jié)構以及相互之間的調(diào)用關系。5.1.1系統(tǒng)庫函數(shù)庫函數(shù)也稱為標準函數(shù),是在C++編譯系統(tǒng)中已經(jīng)預先定義的函數(shù)。C++把一些常用的操作以庫函數(shù)的方式提供給用戶,包括常用的數(shù)學計算函數(shù)(如:sqrt()、fabs()等)、圖形處理函數(shù)、標準輸入/輸出函數(shù)等。按功能對庫函數(shù)進行分類,將同類庫函數(shù)集中在一個頭文件中,用戶只要在程序中包含相應的頭文件,就可以使用該頭文件中的所有庫函數(shù)。

用戶自定義函數(shù)在程序設計過程中,用戶可根據(jù)自己的需要將一段完成功能相對獨立的代碼定義為一個函數(shù),這類函數(shù)稱為用戶自定義函數(shù)。本章將主要介紹用戶自定義函數(shù)的定義和調(diào)用方法。

圖5-1函數(shù)調(diào)用和被調(diào)用的層次關系main()Func1()Func5()Func3()Func2()Func4()函數(shù)定義對于庫函數(shù),在頭文件中已經(jīng)定義好了,調(diào)用函數(shù)前只需包含相應的頭文件即可;對于用戶自定義的函數(shù),要先完成函數(shù)的定義,然后才可以調(diào)用它。根據(jù)函數(shù)定義和使用時參數(shù)的不同,可將函數(shù)分為兩類:無參函數(shù)和有參函數(shù)。

無參函數(shù)

有參函數(shù)

函數(shù)返回值和return語句

5.1.2無參函數(shù)定義無參函數(shù)的一般格式為:

《<類型>》<函數(shù)名>(《void》) {…}//函數(shù)體

<類型>為函數(shù)返回值的類型,它可以是任一標準數(shù)據(jù)類型或?qū)С鰯?shù)據(jù)類型,當沒有返回值時,《類型》必須為void。函數(shù)名為用戶給函數(shù)起的名字,其命名規(guī)則與標識符相同。<函數(shù)名>后的括號”()”稱為函數(shù)調(diào)用運算符,對于無參函數(shù),函數(shù)調(diào)用運算符內(nèi)可以為空,也可以為void。函數(shù)返回值為整型時,可省略類型標識符int。當函數(shù)無返回值時,必須規(guī)定其類型為void。示例示例voidMessage(void){

cout<<”*************\n”;

cout<<”verygood!\n”;

cout<<”*************\n”;}該函數(shù)完成輸出一些問候語。像這類與外部環(huán)境之間沒有任何數(shù)據(jù)交換的函數(shù),通常將其定義為無參函數(shù)。

有參函數(shù)定義有參函數(shù)的一般格式為:

《類型》<函數(shù)名>(<形參表>) {…}//函數(shù)體

有參函數(shù)中《類型》與<函數(shù)名>的含義和要求與無參函數(shù)一致。<形參表>為該函數(shù)的參數(shù)的類型和名字,<形參表>中的參數(shù)稱為形式參數(shù)或形參,形參的個數(shù)是沒有限制的,當超過一個參數(shù)時,參數(shù)間一定要用逗號”,”分隔開,且每個參數(shù)都要有類型說明。示例

在定義有參函數(shù)時,必須標明每個參數(shù)的類型,即使參數(shù)的數(shù)據(jù)類型相同,也不能將參數(shù)合在一起用一個類型說明符。

示例例如,求兩個整數(shù)中的大數(shù),函數(shù)可定義為:

intMax(intx,inty) //A {return(x>y?x:y);}該函數(shù)有兩個整型參數(shù)x,y,函數(shù)的返回值是整型。

如上例A行寫成以下形式就是錯誤的:

Max(intx,y)函數(shù)返回值和return語句函數(shù)的返回值也稱為函數(shù)值。當函數(shù)有返回值時,在函數(shù)體中必須使用return語句來返回該函數(shù)的值。return語句的一般格式為:

return<表達式>;或

return(<表達式>);這里<表達式>可以為任意合法的表達式。當執(zhí)行該語句時,首先求出表達式的值,再將該值轉(zhuǎn)換成函數(shù)定義時規(guī)定的返回值的類型后,將其作為函數(shù)的返回值。

【例5.1】

求三角形的面積

函數(shù)調(diào)用C++中,函數(shù)的功能是通過在程序中對其調(diào)用來實現(xiàn)的。調(diào)用一個函數(shù),就是把控制權轉(zhuǎn)去執(zhí)行該函數(shù)的函數(shù)體,函數(shù)體執(zhí)行完之后,再將控制權轉(zhuǎn)到調(diào)用函數(shù)處。

無參函數(shù)的調(diào)用格式

有參函數(shù)的調(diào)用格式

函數(shù)調(diào)用的使用方式

關于形參和實參的幾點說明

【例5.2】

輸入三個實數(shù),求出其中的最大數(shù)圖5-25.1.3無參函數(shù)的調(diào)用格式無參函數(shù)的調(diào)用格式一般為:

<函數(shù)名>()在調(diào)用無參函數(shù)前,必須先定義與它同名的無參函數(shù)。如:Message函數(shù)定義過之后,可以使用Message();來調(diào)用。

有參函數(shù)的調(diào)用格式有參函數(shù)的調(diào)用格式一般為:

<函數(shù)名>(<實參表>)<實參表>中的參數(shù)稱為實際參數(shù)或?qū)崊?,每個實參可以是任一合法的表達式。實參與形參不同,在實參前沒有數(shù)據(jù)類型說明符。在調(diào)用有參函數(shù)前,也必須先定義,另外,調(diào)用有參函數(shù)時實參表和形參表的參數(shù)類型、個數(shù)必須匹配。

如:Max(4,9);及Max(a*4,b);函數(shù)的調(diào)用過程是:先計算各實參表達式的值(對有參函數(shù)),然后將所求的值傳遞給相應的形參,執(zhí)行函數(shù)體,執(zhí)行完畢再返回到函數(shù)的調(diào)用處,繼續(xù)執(zhí)行其后繼語句。

函數(shù)調(diào)用的使用方式對于有返回值的函數(shù),可以用兩種方式調(diào)用:一種方式是函數(shù)調(diào)用出現(xiàn)在表達式中,其值(也稱為函數(shù)值)參與表達式的運算;另一種方式是用一個語句來實現(xiàn)調(diào)用,即在調(diào)用格式后加上一個分號,構成函數(shù)調(diào)用語句,在這種情況下,函數(shù)返回值不起任何的作用。

對于沒有返回值的函數(shù),函數(shù)調(diào)用只能通過函數(shù)調(diào)用語句實現(xiàn)。

關于形參和實參的幾點說明定義函數(shù)時指定的形參,在未出現(xiàn)函數(shù)調(diào)用時,它們不占用內(nèi)存中的存儲單元。只有在函數(shù)調(diào)用時,形參才被分配內(nèi)存單元,在調(diào)用結(jié)束后,形參所占的內(nèi)存單元也被釋放。

調(diào)用時是將實參的值傳遞給形參,只是一個單向的傳遞關系。這是我們所說的“值傳遞”,形參值的改變不會影響實參的值。

實參與形參的類型應相同。當類型不一致時,則它們應該兼容,即按照不同類型數(shù)值的賦值規(guī)則,將實參轉(zhuǎn)換為形參的數(shù)據(jù)類型后再傳遞給形參。

圖5-2

函數(shù)的調(diào)用過程main()函數(shù)調(diào)用函數(shù)Max(a,b)函數(shù)Max(int,int)執(zhí)行函數(shù)Max(int,int)的函數(shù)體將Max(a,b)的返回值賦給t調(diào)用函數(shù)Max(c,t)…結(jié)束向Max函數(shù)傳遞實參a,b向Max函數(shù)傳遞實參c,t函數(shù)的原型說明與值調(diào)用函數(shù)的原型說明

函數(shù)的值調(diào)用

5.2函數(shù)的原型說明C++中,與變量一樣,函數(shù)的定義和使用也必須遵循先定義后使用的原則。如果函數(shù)的調(diào)用在函數(shù)的定義之前,就會出現(xiàn)編譯錯誤。

如果函數(shù)調(diào)用在前、定義在后,則在函數(shù)調(diào)用之前,必須要對被調(diào)用的函數(shù)作原型說明。函數(shù)原型說明是一條語句,它必須以分號結(jié)束。函數(shù)原型說明的一般格式函數(shù)原型說明的目的是告訴編譯程序,該函數(shù)的參數(shù)個數(shù)、各參數(shù)的類型和返回值類型。函數(shù)原型說明可以出現(xiàn)在程序中的任何位置,只要在調(diào)用前即可,且對函數(shù)原型說明的次數(shù)沒有限制。

5.2.1函數(shù)原型說明的一般格式《類型》<函數(shù)名>(<形參表>);

《類型》<函數(shù)名>(<形參類型說明表>);

函數(shù)原型說明的形參和返回值的類型必須與對應的函數(shù)定義一致,對于第一種格式,原型說明中形參表的形參名可以和定義時的形參名不一致,又由于形參在原型說明中并不起任何作用,因此可以省略形參名(即第二種格式)。

函數(shù)的值調(diào)用C++中,形參與實參的結(jié)合方式有三種:傳值調(diào)用、傳地址調(diào)用和引用調(diào)用。

傳值調(diào)用簡稱為值調(diào)用。值調(diào)用的特點是:在被調(diào)用函數(shù)的執(zhí)行過程中,只能改變形參,不能改變實參。【例5.3】值傳遞應用——兩數(shù)交換

圖5-3值傳遞的好處是使得函數(shù)具有完全的獨立性,函數(shù)的執(zhí)行對其外界的變量沒有影響。在值傳遞的情況下,函數(shù)只能通過return語句返回一個值或不返回任何值。要用函數(shù)實現(xiàn)兩個數(shù)參數(shù)的交換,值傳遞是無法實現(xiàn)的,可以用地址傳遞或引用傳遞的方法。

5.2.2圖5-3兩數(shù)交換函數(shù)調(diào)用過程示意圖35353553axbyybxa(a)交換前(b)交換后執(zhí)行函數(shù)Swap(int,int)函數(shù)的嵌套和遞歸調(diào)用函數(shù)的嵌套調(diào)用

函數(shù)的遞歸調(diào)用

5.3函數(shù)的嵌套調(diào)用C++語言的函數(shù)之間是相互平行、獨立的,在定義一個函數(shù)時,不允許在其函數(shù)體內(nèi)再定義另一個函數(shù),即函數(shù)不允許嵌套定義。但是函數(shù)之間的嵌套調(diào)用是可以的,即在定義一個函數(shù)時,在函數(shù)體內(nèi)又調(diào)用另一個函數(shù)。圖5-4【例5.4】求一元二次方程ax2+bx+c=0的根

5.3.1圖5-4嵌套調(diào)用⑤⑥④③⑦②⑧main函數(shù)b函數(shù)a函數(shù)調(diào)用a函數(shù)結(jié)束調(diào)用b函數(shù)⑨①函數(shù)的遞歸調(diào)用在函數(shù)A的定義中調(diào)用函數(shù)A,或在函數(shù)A的定義中調(diào)用函數(shù)B,而在函數(shù)B的定義中又調(diào)用了函數(shù)A,這類函數(shù)的自調(diào)用關系稱為遞歸調(diào)用。前一種情況稱為直接遞歸,而后一種情況稱為間接遞歸。在C++語言中,這兩種遞歸調(diào)用都是允許的。

【例5.5】用函數(shù)遞歸調(diào)用方法求5!

【例5.6】將參數(shù)逐位正序和反序輸出

【例5.7】Hanoi(漢諾塔)問題

5.3.2【例5.5】用函數(shù)遞歸調(diào)用方法求4!分析:由遞推公式n!=n*(n-1)!,所以求n!的問題可以轉(zhuǎn)化為求(n-1)!的問題,(n-1)!=(n-1)*(n-2)!,因此求(n-1)!的問題可以轉(zhuǎn)化為求(n-2)!的問題,依此類推,直到轉(zhuǎn)化為求1!的問題,根據(jù)定義,1!=1,則從1!=1開始將上述過程逆向求解,就可以求出n!。這種求解問題的方法可用函數(shù)遞歸調(diào)用方法實現(xiàn)算法演示程序代碼算法演示程序代碼#include<iostream.h>int

f(intn){ if(n==0||n==1)return1; //A elsereturnn*f(n-1); //B }voidmain(void){cout<<<<f(4)<<'\n';}【例5.6】將參數(shù)逐位正序和反序輸出設計兩個函數(shù),其參數(shù)都為整型,分別將參數(shù)逐位正序和反序輸出。要求用遞歸函數(shù)實現(xiàn)。

分析:要實現(xiàn)逐位正序或反序輸出一個整數(shù),則須獲取它的各位數(shù)字。如1234,則用1234%10獲得它的個位數(shù),求十位數(shù),則須先將個位數(shù)去掉,即1234/10,結(jié)果為123,再求個位數(shù)即可,依此類推。求一個整數(shù)K的各位數(shù)字時其遞推關系為:

f1=Ktn=fn%10fn+1=fn/10

其中tn為整數(shù)K的第n位數(shù)字(從右數(shù)起),fn為去掉K的右邊n-1位數(shù)后剩下的數(shù)。而該遞推關系的結(jié)束條件為fn=0。程序代碼

【例5.7】Hanoi(漢諾塔)問題這是一個經(jīng)典的數(shù)學問題:有三個塔A、B、C,開始時A塔上有n個盤子,盤子大小不等,大的在下,小的在上,如圖5-6所示。要求將這n個盤子從A塔移到C塔,但每次只允許移一個盤子,而且在移動過程中始終保持大盤子在下,小盤子在上,在移動過程中可以利用B塔。分析移動步驟遞歸公式程序代碼圖5-6漢諾塔問題分析可以用遞歸的思想來考慮這個問題。假設能將A塔中最上面的n-1個盤子借助于C塔移動到B塔,然后將A塔中剩下的一個盤子移動到C塔,再將B塔中的n-1個盤子借助于A塔移動到C塔,這樣問題就解決了。因此接下來就要考慮如果一個塔內(nèi)有n-1個盤子,如何借助于另一個塔移動到C塔,與n個盤子的思考方法一樣,此時可考慮先移動n-2個盤子,依次類推,當變成移動一個盤子時,遞歸結(jié)束。

移動步驟將n個盤子從A塔移到C塔上,可以分解為以下3個步驟:

將A塔上的n-1個盤子借助C塔先移到B塔上;

將A塔上剩下的1個盤子移到C塔上;

將n-1個盤子從B塔借助于A塔移到C塔上。

其中第一步和第三步又可以分解為類似的三步,依次類推,直到A中只剩下一個盤子時,遞歸結(jié)束。

遞歸公式將k-1個盤子從一個塔借助于另一個塔移動到第三個塔上(k>1),它是一個遞歸的過程。用函數(shù)Hanoi(intk,charA,charB,charC)表示,其中第一個參數(shù)k為要移動盤子的個數(shù),第二個參數(shù)A為初始塔,第三個參數(shù)B為中間塔,第四參數(shù)C為目標塔。該函數(shù)的功能是將A塔中的k個盤子通過B塔移動到C塔。

將1個盤子從一個塔移到另一塔上。用Move(charA,charB)實現(xiàn),即將A塔中的盤子移動到B塔中去。

作用域和存儲類作用域是指程序中所說明的標識符的適用范圍。C++中的作用域共分為:塊作用域、文件作用域、函數(shù)原型作用域、函數(shù)作用域和類作用域。存儲類型決定了變量的生存期,即何時為變量分配存儲空間以及何時撤消存儲空間。在定義變量時,通常根據(jù)該變量的不同用途,為其指定相應的存儲類型。作用域

存儲類型

5.4作用域作用域描述的是標識符起作用的范圍,這里的標識符可以泛指變量、常量或函數(shù)原型說明等。但對編譯預處理中宏定義中的宏名卻不適用。

塊作用域

函數(shù)原型作用域

函數(shù)作用域

文件作用域

5.4.1塊作用域用花括號括起來的程序段構成一個塊(即復合語句),在塊內(nèi)說明的標識符只能在該塊內(nèi)使用,其作用域就稱為塊作用域。具有塊作用域的標識符的有效范圍是從聲明處開始,到塊結(jié)束處為止,該作用域的范圍是具有局部性的。因此,在塊內(nèi)定義的變量稱為局部變量。

示例對于塊作用域,C++語言做如下的規(guī)定:

塊嵌套問題

對一些特殊情況,C++作不同的處理

塊嵌套問題塊嵌套問題。當塊A包含塊B,則在塊B中可以使用在塊A中定義的標識符,反過來則不行。另外當在塊A中定義的標識符與塊B中定義的標識符同名時,則在塊B中的標識符將屏蔽塊A中的同名標識符,即局部優(yōu)先

【例5.8】塊嵌套中標識符的使用

對一些特殊情況,C++作不同的處理對if語句或switch語句的表達式中定義的標識符,其作用域在該語句內(nèi)。例如在for語句的第一個表達式中聲明的標識符,其作用域為包含該for循環(huán)語句的那個塊。例如

定義有參函數(shù)時,形式參數(shù)的作用域為塊作用域,即它的適用范圍為整個函數(shù)體

例如voidBlock4(){

if(inti=2) //i的作用域從此行開始

i+=1; else i+=2;

//i的作用域到此行結(jié)束

cout<<i<<endl; //錯誤,i沒有定義}例如voidBlack5(){ for(inti,j=0;i<10;i++)//A {

intj=9; //與A行定義的j沒有沖突,

cout<<i+j<<’\t’; }

inti=10; //錯誤,與A行定義的i同名

cout<<”i=”<<i<<’\n’; }函數(shù)原型作用域函數(shù)原型聲明(沒有函數(shù)體)中參數(shù)的作用域稱為函數(shù)原型作用域。此時,參數(shù)的作用域開始于函數(shù)原型聲明的左括號,結(jié)束于函數(shù)原型聲明的右括號。比如:

voidFun(intx,inty); x=2;//錯誤,x沒有定義

由于函數(shù)原型聲明中的參數(shù)名與函數(shù)定義以及函數(shù)調(diào)用均無關,因此,函數(shù)原型聲明中參數(shù)的標識符可以與函數(shù)定義中參數(shù)的標識符不同,甚至在函數(shù)原型聲明時可以只列出參數(shù)的類型,而沒有參數(shù)名。比如:

voidFun(int,int);函數(shù)作用域函數(shù)作用域是指在函數(shù)體內(nèi)定義的標識符在其定義的函數(shù)內(nèi)均有效。該標識符在函數(shù)的任何位置都可以使用它,不受先定義后使用的限制,也不受函數(shù)體中嵌套塊的限制。C++中,只有標號具有函數(shù)作用域,即在一個函數(shù)體內(nèi)定義的標號,在該函數(shù)的任何位置都可以調(diào)用該標號(條件語句、循環(huán)語句、switch語句中的特殊情形除外)。且正是由于標號為函數(shù)作用域,因此在一個函數(shù)中不能用goto語句調(diào)用另一個函數(shù)中的標號。例如

例如voidFun(intx){

inty;lab1: cout<<”輸入y:”<<’\n’;//A

cin>>y;

{ lab1:y+=x;//錯誤,與A行的標號同名,盡管它們屬于不同的塊

if(!y)gotolab1; elsegotolab2; //錯誤,不能調(diào)用其它函數(shù)中的標號

}}voidFun1(intx){lab2:cout<<x<<’\n’;}文件作用域具有文件作用域的標識符是在所有函數(shù)定義之外定義的,即該標識符不隸屬于任何塊。它的作用域從標識符聲明處開始,一直到文件結(jié)束。具有文件作用域的變量稱為全局變量。當在塊作用域內(nèi)的變量與全局變量同名時,局部變量優(yōu)先。此時若想在該塊中調(diào)用全局變量,可通過作用域運算符“::”來實現(xiàn)。

【例5.9】在塊作用域內(nèi)引用文件作用域同名變量

存儲類型作用域是從空間上對標識符進行劃分的,而存儲類型則是從變量存在的時間(即生存期)來劃分變量。變量的存儲類型可以分為靜態(tài)存儲方式和動態(tài)存儲方式兩大類。

在C++中,變量的存儲類型分為四種:自動(auto)類型、寄存器(register)類型、靜態(tài)(static)類型和外部(extern)類型。

自動類型變量

靜態(tài)類型變量

寄存器類型變量

外部類型變量

5.4.2靜態(tài)存儲方式

在程序開始執(zhí)行時就為變量分配存儲空間,直到程序執(zhí)行結(jié)束時,才收回為變量分配的存儲空間,這種變量稱為靜態(tài)存儲變量,其生命期為整個程序執(zhí)行過程。動態(tài)存儲方式

在程序的執(zhí)行過程中,為其分配存儲空間的變量稱為動態(tài)存儲變量。對于動態(tài)存儲變量,當程序運行到該變量的定義處時為其分配存儲空間,而當程序運行到該變量所在作用域的結(jié)束處時自動收回為其分配的存儲空間。因此動態(tài)存儲類型的變量的生存期為其所在的作用域。

自動類型變量用關鍵字auto修飾的變量稱為自動類型的變量。在說明局部變量時,編譯系統(tǒng)默認其為自動類型變量,因此通常省略關鍵字auto。自動類型的變量只能是局部類型的變量,不可能為全局變量。示例自動類型變量屬于動態(tài)存儲類型變量。上例中的x,y的生存期為其所在的作用域。具體說,對x而言,在A行為其分配4個字節(jié)的存儲空間,到B行就收回該存儲空間。在使用自動類型的變量之前必須對其賦初值。否則,其值為一個不確定的隨機數(shù)。

autointI;//錯誤,全局變量不能用關鍵字 //auto修飾voidAu(void){autointx=1;//Ax為自動類型變量

chary=’a’; //省略關鍵字auto系統(tǒng)默 //認y為自動類型變量} //B靜態(tài)類型變量靜態(tài)存儲類型的變量有兩種:全局變量和靜態(tài)類型變量。用關鍵字static修飾的變量稱為靜態(tài)類型變量。靜態(tài)類型變量可以為局部變量,也可以為全局變量。靜態(tài)類型變量屬于靜態(tài)存儲變量,即在程序開始運行時就為其分配存儲空間,當程序結(jié)束時才釋放其所占用的存儲空間。因此在整個程序執(zhí)行過程中,靜態(tài)變量都始終占用同一個存儲空間。

【例5.10】使用靜態(tài)類型的局部變量

寄存器類型變量用關鍵字register修飾的局部變量稱為寄存器類型變量,這類變量也采用動態(tài)存儲的分配方式。在編譯過程中,編譯器不為寄存器類型的變量分配內(nèi)存空間,而是直接使用CPU中的寄存器,以便提高對這類變量的存取速度。寄存器類型變量主要用于控制循環(huán)次數(shù)等不需要長期保存值的變量。

【例5.11】利用寄存器類型變量求l~15的階乘。

#include<iostream.h>voidmain(void){ registerfloatFact=1; //定義實型寄存器變量Fact for(registerinti=1;i<=15;i++)//定義整型寄存器變量i { Fact*=i;

cout<<i<<"!="<<Fact<<'\n'; }}外部類型變量用關鍵字extern修飾的變量稱為外部類型變量,外部類型變量必須是全局變量。在C++中,有兩種情況下需要使用外部類型變量。

在同一個源程序文件中,當在全局變量的定義之前使用該變量時,在使用前要對該變量進行外部類型變量聲明?!纠?.12】外部類型變量的聲明

當程序由多個文件組成時,若在一個源程序文件中要引用在另一個源程序中定義的全局變量,在引用前必須對所引用的變量進行外部聲明?!纠?.13】文件間共享全局變量

【例5.12】外部類型變量的聲明#include<iostream.h>int

Max(int

x,inty){returnx>y?x:y;}

voidmain(void){ externinta,b; //A

cout<<Max(a,b); //B}inta=12,b=-4;【例5.13】文件間共享全局變量externfloatx; //A voidmain(void) { x++;cout<<x<<’\n’;}在文件c2.cpp中有:

floatx=100; //B

內(nèi)聯(lián)函數(shù)一般函數(shù)在調(diào)用時,要花費將實參和返回地址壓入棧,然后轉(zhuǎn)入執(zhí)行被調(diào)用函數(shù)等一系列開銷。

C++中的內(nèi)聯(lián)函數(shù),將省略這類的開銷。編譯系統(tǒng)對內(nèi)聯(lián)函數(shù)的處理與一般函數(shù)的處理方式不同,在編譯調(diào)用內(nèi)聯(lián)函數(shù)的語句時,編譯器將內(nèi)聯(lián)函數(shù)的代碼插入到函數(shù)調(diào)用處,在運行過程中,將直接運行插入的代碼,從而可以提高程序運行的速度。將一個函數(shù)聲明為內(nèi)聯(lián)函數(shù)時,只要在函數(shù)定義前加關鍵字inline即可,聲明格式【例5.14】用內(nèi)聯(lián)函數(shù)計算立方體的體積

5.5內(nèi)聯(lián)函數(shù)聲明格式

inline<類型><函數(shù)名>(《參數(shù)表》) {

…//函數(shù)體

}【例5.14】用內(nèi)聯(lián)函數(shù)計算立方體的體積#include<iostream.h> inlinefloatCube(floata){returna*a*a;}

voidmain(){

cout<<”輸入立方體的邊長:”; floatside;

cin>>side;

cout<<”邊長為”<<side<<”的立方體的體積為:”

<<Cube(side)<<’\n’; //A}具有缺省參數(shù)值的函數(shù)在定義具有缺省參數(shù)值的函數(shù)時,要為參數(shù)指定一個值。比如:

voidFun(intx=1,inty=2){…}【例5.15】具有缺省參數(shù)值的延時函數(shù)

【例5.16】求圓柱體的體積

5.6【例5.15】具有缺省參數(shù)值的延時函數(shù)#include<iostream.h>voidDelay(intn=1000) //A{ for(;n>0;n--); }

voidmain(void){cout<<"延時500個單位時間…\n";Delay(500); //Bcout<<"延時1000個單位時間…\n";Delay(); //C}【例5.16】求圓柱體的體積#include<iostream.h>#definePI3.1415926floatVolume(floatr,floath=10); //A

voidmain(void){ floatr,h;

cout<<"輸入第一個圓柱體的半徑和高度:";

cin>>r>>h;

cout<<"第一個圓柱體的體積為:"<<Volume(r,h)<<'\n';

cout<<"輸入第二個圓柱體的半徑:";

cin>>r;

cout<<"第二個圓柱體的體積為:"<<Volume(r)<<'\n'; floatVolume(float=5,float=20); //B

cout<<"第三個圓柱體的體積為:"<<Volume()<<'\n';//C}floatVolume(floatr,floath) //D { return(PI*r*r*h); }函數(shù)重載函數(shù)的重載又稱函數(shù)名重載,是指實現(xiàn)不同功能的函數(shù)可以具有相同的函數(shù)名。

C++編譯器在進行函數(shù)調(diào)用時是根據(jù)函數(shù)名和函數(shù)的參數(shù)來決定調(diào)用哪一個函數(shù)的,因此,對于函數(shù)名重載問題,要區(qū)分函數(shù)名相同的函數(shù),只有從它們的參數(shù)上進行區(qū)分。要實現(xiàn)函數(shù)名重載,它們的參數(shù)必須滿足下面兩個條件之一:參數(shù)的個數(shù)不同參數(shù)的類型不同【例5.17】利用參數(shù)類型的不同實現(xiàn)重載函數(shù)

【例5.18】利用參數(shù)個數(shù)不相同實現(xiàn)重載函數(shù)在定義重載函數(shù)時要注意的幾點

5.7【例5.17】利用參數(shù)類型的不同實現(xiàn)重載函數(shù)#include<iostream.h>

int

Abs(intx){ //A

cout<<”調(diào)用函數(shù)Abs(int).”<<’\n’; returnx>=0?x:-x; } doubleAbs(doublex) { //B

cout<<”調(diào)用函數(shù)Abs(double).”<<’\n’; returnx>=0?x:-x; } voidmain() {

cout<<”-20的絕對值是:”<<Abs(-20)<<endl;//C

cout<<”-111.11的絕對值是:”<<Abs(-111.11)<<endl;//D }【例5.18】利用參數(shù)個數(shù)不相同實現(xiàn)重載函數(shù)#include<iostream.h>int

max(int

a,intb);int

max(int

a,int

b,intc);int

max(int

a,int

b,int

c,intd);voidmain(){

cout<<max(3,5)<<endl;

cout<<max(-7,9,0)<<endl;

cout<<max(23,15,3,6)<<endl; }int

max(int

a,intb){ returna>b?a:b;}int

max(int

a,int

b,intc){ intt=max(a,b); returnmax(t,c);}int

max(int

a,int

b,int

c,intd){ intt1=max(a,b);

intt2=max(c,d); returnmax(t1,t2);}在定義重載函數(shù)時要注意的幾點定義的重載函數(shù)必須具有不同的參數(shù)個數(shù)或不同的參數(shù)類型,只有這樣編譯系統(tǒng)才能根據(jù)不同的參數(shù)決定調(diào)用哪一個函數(shù)版本

僅僅是函數(shù)返回值不同并不能區(qū)分兩個函數(shù),因此不能根據(jù)函數(shù)的返回值定義函數(shù)的重載。例如

int

sum(inta){…}voidsun(inta) {…}這兩個函數(shù)僅僅返回值不同,編譯時將發(fā)生二義性錯誤。編譯預處理C++語言中使用一些特殊的命令,在編譯之前先對這些命令進行“預處理”,然后將結(jié)果和源程序一起進行編譯處理,得到目標代碼,此過程稱為編譯預處理。這些命令稱為編譯預處理指令,它們不是C++語句,一律以#開頭,以回車符結(jié)束,每一條預處理指令獨占一行。

根據(jù)編譯預處理功能的不同,將其分為三類:宏定義#define、文件包含#include和條件編譯#if。

“文件包含”處理

宏定義

條件編譯

5.8所謂“文件包含”處理是指一個源文件可以將另一個源文件的全部內(nèi)容包含進來?!拔募笨赏ㄟ^#include編譯預處理指令來實現(xiàn),格式為:

#include<文件名>或

#include“文件名”

“文件包含”的處理過程

【例5.19】文件包含的應用

關于#include編譯預處理指令需要說明的幾點

“文件包含”處理5.8.1這種格式是標準格式,主要用于包含C++系統(tǒng)所提供的頭文件。當C++預處理器遇到該指令時,就到C++系統(tǒng)目錄的include子目錄下搜索給出的文件,并把它嵌入到當前文件中。

這種格式既適合于用戶自己建立的文件,也適合于C++系統(tǒng)提供的頭文件。當C++預處理器遇到該指令后,首先在當前工作目錄中查找所包含的文件,如果找不到,再按標準方式進行搜索。

“文件包含”的處理過程包含#include“File2.h”ABBAFile1.cppFile2.hFile1.cpp(a)(b)(c)圖3-7“文件包含”示意圖編譯預處理【例5.19】文件包含的應用設文件File1.h的內(nèi)容為:intx=200,y=100; floatx1=25.6,x2=28.9;設文件File2.cpp的內(nèi)容為:#include“File1.h”//A#include<iostream.h>voidmain(void) { cout<<x<<’\t’<<y<<’\n’;

cout<<x1<’\t’<<x2<<’\n’; }intx=200,y=100;floatx1=25.6,x2=28.9;#include<iostream.h>voidmain(void){cout<<x<<’\t’<<y<<’\n’;

cout<<x1<<’\t’<<x2<<’\n’;}關于#include編譯預處理指令需要說明的幾點被包含的文件通常是頭文件,也可以為其他類型的文件,如源程序文件或文本文件等;

一個#include命令只能指定一個被包含文件;一個被包含的文件中也可以包含其他文件,即文件的包含可以是嵌套的,嵌套的層次也沒有限制;

#include指令可以出現(xiàn)在程序中的任何位置,通常是放在程序的開頭

由于被包含的文件(File1.h)與其所在的文件(File2.cpp)在預編譯后已稱為合并到一個文件中,因此,F(xiàn)ile2.cpp可直接訪問File1.h中的全局變量,此時可不用extern聲明。同樣,F(xiàn)ile2.cpp中也能直接訪問File1.h中的函數(shù)

宏定義

宏定義用#define編譯預處理指令實現(xiàn),可分為不帶參數(shù)的宏定義和帶參數(shù)的宏定義。不帶參數(shù)的宏常用于定義標識符常量,即可將一個常量指定給一個標識符,它與const類型的變量類似;帶參數(shù)的宏可將一個表達式指定給一個帶參數(shù)的標識符,它與函數(shù)的功能類似。

不帶參數(shù)的宏定義

【例5.20】不帶參數(shù)的宏的使用

帶參數(shù)的宏定義

【例5.21】帶參數(shù)的宏定義的使用

5.8.2不帶參數(shù)的宏定義定義不帶參數(shù)宏的一般格式為:

#define標識符

字符序列

其中標識符稱為宏名,它可以是任意合法的標識符,通常為大寫。字符序列為一串字符,它可由任意的字符構成,包括空格。例如:

#definePI3.1415926不帶參數(shù)的宏定義及其使用需說明的幾點

不帶參數(shù)的宏定義及其使用需說明的幾點宏名可以為任意的合法標識符,常用大寫字母表示

宏定義中可以用已定義過的宏名,但對用雙引號括起來的字符序列中的字符,即使與宏名相同,也不進行宏擴展。例如

宏擴展時,只對宏名作簡單的代換,不作任何計算,也不作任何語法檢查;比如宏定義不是C++語句,不必在行末加分號,如果加了分號則會連分號一起進行宏擴展,例如:一個宏通常在一行內(nèi)定義完,并以換行符結(jié)束。當多于一行時,須使用轉(zhuǎn)義字符“

溫馨提示

  • 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論