C__帶默認值參數的函數說明
1.float area(float r=6.5);
指定r的默認值為6.5,如果在調用此函數時,確認r的值為6.5,則可以不必給出實參的值,如
area( ); //相當於area(6.5);
如果不想使形參取此默認值,則通過實參另行給出。如area(7.5); //形參得到的值為7.5,而不是6.5
這種方法比較靈活,可以簡化編程,提高運行效率。
2.如果有多個形參,可以使每個形參有一個默認值,也可以只對一部分形參指定默認值,另一部分形參不指定默認值。
如有一個求圓柱體體積的函數,形參h代表圓柱體的高,r為圓柱體半徑。函數原型如下:
float volume(float h,float r=12.5); //只對形參r指定默認值12.5
函數調用可以采用以下形式:
volume(45.6); //相當於volume(45.6,12.5)
volume(34.2,10.4) //h的值為34.2,r的值為10.4
3.實參與形參的結合是從左至右順序進行的。因此指定默認值的參數必須放在形參表列中的最右端,否則出錯。
例如:
void f1(float a,int b=0,int c,char d=′a′); //不正確
void f2(float a,int c,int b=0, char d=′a′); //正確
如果調用上面的f2函數,可以采取下面的形式:
f2(3.5, 5, 3, ′x′) //形參的值全部從實參得到
f2(3.5, 5, 3) //最后一個形參的值取默認值′a′
f2(3.5, 5) //最后兩個形參的值取默認值,b=0,d=′a′
可以看到,在調用有默認參數的函數時,實參的個數可以與形參的個數不同,實參未給定的,從形參的默認值得到值。利用這一特性,可以使函數的使用更加靈活。例如例4.7求2個數或3個數中的最大數。也可以不用重載函數,而改用帶有默認參數的函數。
例4.8 求2個或3個正整數中的最大數,用帶有默認參數的函數實現。
#include <iostream>
using namespace std;
int max(int a, int b, int c=0);//函數聲明,形參c有默認值
int main( )
{
int a,b,c;
cin>>a>>b>>c;
cout<<″max(a,b,c)=″<<max(a,b,c)<<endl; //輸出3個數中的最大者
cout<<″max(a,b)=″<<max(a,b)<<endl; //輸出2個數中的最大者
return 0;
}
int max(int a,int b,int c) //函數定義
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
運行情況如下:
14 -56 135↙
max(a,b,c)=135
max(a,b)=14
在使用帶有默認參數的函數時有兩點要注意:
(1) 如果函數的定義在函數調用之前,則應在函數定義中給出默認值。如果函數的定義在函數調用之后,則在函數調用之前需要有函數聲明,此時必須在函數聲明中給出默認值,在函數定義時可以不給出默認值(如例4.8)。
(2) 一個函數不能既作為重載函數,又作為有默認參數的函數。因為當調用函數時如果少寫一個參數,系統無法判定是利用重載函數還是利用默認參數的函數,出現二義性,系統無法執行。
(3) 在函數聲明和函數定義中,默認參數必須相同。這是錯的,因為定義時有實參,但是聲明的時候沒有實參的話那么定義的時候的實參沒有用,等於沒有提供實參!!
C++__帶默認值參數的函數說明
我們可以賦予函數參數默認值。所謂默認值就是在調用時,可以不寫某些參數的值,編譯器會自動把默認值傳遞給調用語句中。默認值可以在聲明或定義中設置;也可在聲明或定義時都設置,都設置時要求默認值是相同的。
關於默認值要注意幾點:
(1) .若在定義時而不是在聲明時置默認值,那么函數定義一定要在函數的調用之前。因為聲明時已經給編譯器一個該函數的向導,所以只在定義時設默認值時,編譯器只有檢查到定義時才知道函數使用了默認值。若先調用后定義,在調用時編譯器並不知道哪個 參數設了默認值。所以我們通常是將默認值的設置放在聲明中而不是定義中。
(2) .不能將實際值傳遞給引用類型的參數。可以將變量作引用類型參數的默認值,這時變量必須是已經聲明且是全局變量。
聲明函數時,要將類或結構中定義 的靜態成員變量作為默認值,若該類或結構還未創建實例,那要在此靜態成員變量前加上作用域操作符(::)。
若已聲明了類或結構的實例,則引用其成員變量作為函數參數的默認值,就要在變量前加上實例名和成員操作符(.)。
(3) .若給某一參數設置了默認值,那么在參數表中其后所有的參數都必須也設置默認值,否則,由於函數調用時可不列出已設置默認值的參數,編譯器無法判斷在調用時是否有參數遺漏。(實參和形參是從左向右結合的)
(4) .在調用時,若給已經設置默認值的參數傳遞實際值,既要取代默認值,則在參數表中被取代參數的左邊所定義的所有參數,無論是否有默認值,都必須傳遞實際參數。
這也是因為函數調用時可不列出已設置默認值的參數。假若被取代參數的左邊既有設置了默認值的參數也有未設置默認值的參數,若不對其左邊的所有參數傳遞實際參數,編譯器也就無法分辨傳遞的這個取代值到底要傳遞給哪個參數。
例如有以下函數聲明:
int FunctionOne(int x,int y=0,int z=0,int w=0);
我們要給z 傳遞整型值8,作如下調用:
FunctionOne(8);
顯然,編譯器無法確定這個8 到底要傳遞給哪個參數。為了達到我們的目的,必須這樣調用:
FunctionOne(0,0,8);
這是x 被傳遞了0,y 被傳遞了 0,z 被傳遞了8
*******************************************************************************************
第九節 默認參數的函數
1.默認參數的目的
C++可以給函數定義默認參數值。通常,調用函數時,要為函數的每個參數給定對應的實參。例如:
void delay(int loops); //函數聲明
void delay(int loops) //函數定義
{
if(100ps==0)
return;
for(int i=0;i<loops,i++);
}
無論何時調用delay()函數,都必須給loops傳一個值以確定時間。但有時需要用相同的實參反復調用delay()函數。C++可以給參數定義默認值。如果將delay( )函數中的loops定義成默認值1000, 只需簡單地把函數聲明改為:
void delay(int loops=1000);
這樣,無論何時調用delay()函數,都不用給loops賦值,程序會自動將它當作值1000進行處理。例如,調用:
delay(2500); //loops設置為2500
delay(); //ok:loops采用默認值1000
調用中,若不給出參數,則按指定的默認值進行工作。
允許函數默認參數值,是為了讓編程簡單,讓編譯器做更多的檢查錯誤工作。
2.默認參數的聲明
默認參數在函數聲明中提供,當又有聲明又有定義時,定義中不允許默認參數。如果函數只有定義,則默認參數才可出現在函數定義中。例如:
void point(int=3,int=4); //聲明中給出默認值
void point(intx,inty) //定義中不允許再給出默認值
{
cout <<x<<endl;
cout <<y<<endl;
}
3.默認參數的順序規定
如果一個函數中有多個默認參數,則形參分布中,默認參數應從右至左逐漸定義。當調用函數時,只能向左匹配參數。例如:
void func(int a=1,int b,int c=3, int d=4); //error
void func(int a, int b=2,int c=3,int d=4); //ok
對於第2個函數聲明,其調用的方法規定為:
func(10,15,20,30); //ok:調用時給出所有實參
func(); //error:參數a沒有默認值
func(2,12); //ok:參數c和d默認
func(2,15,20); //error:只能從右到左順序匹配默認 (這好像有異議)
4.默認參數與函數重載
默認參數可將一系列簡單的重載函數合成為一個。例如, 下面3個重載函數:
void point(int,int){//...}
void point(int a){return point(a,4);}
void point(){return point(3,4);}
可以用下面的默認參數的函數來替代:
void point(int=3,int=4);
當調用“point();”時,即調用“point(3,4);” 它是第3個聲明的重載函數。
當調用“point(6);”時,即調用“point(6,4);”,它是第2個聲明的重載函數。
當調用“point(7,8);”時,即調用第1個聲明的重載函數
如果一組重載函數(可能帶有默認參數)都允許相同實參個數的調用,將會引起調用的二義性。例如:
void func(int); //重載函數之一
void func(int,int=4); //重載函數之二,帶有默認參數
void func(int=3,int=4); //重載函數之三,帶有默認參數
func(7); //error: 到底調用3個重載函數中的哪個?
func(20,30) //error:到底調用后面2個重載函數的哪個?
5.默認值的限定
默認值可以是全局變量、全局常量,甚至是一個函數。例如:
int a=1;
int fun(int);
int g(int x;fun(a)); //ok:允許默認值為函數
默認值不可以是局部變量,因為默認參數的函數調用是在編譯時確定的,而局部變量的位置與值在編譯時均無法確定。例如:
void fun()
{
int i;
void g(int x=i); //error:處理g()函數聲明時,i不可見
}
本章小結
隨着程序量和程序復雜度的不斷增加,最好的辦法是把程序分成更小,更容易管理的模塊,這種模塊就是函數。
函數名最好能反映出所要完成的任務。
函數可以把數據返回給調用者,若函數要返回一個值,必須在函數名前規定返回值的類型,若函數沒有返回值,則類型為void。
程序通過參數把信息傳遞給函數,若函數需要接受參數,就必須給參數指定名稱及類型。
C++必須知道函數的返回類型以及接受的參數個數和類型, 如果函數的定義出現在函數調用之后,就必須在程序的開始部分用函數原型進行聲明。
局部變量是在函數內部定義的,只能被定義該變量的函數訪問。全局變量是指其作用域貫穿程序始終的變量。定義全局變量要在程序開始時進行,並且放在所有函數的外面。
靜態局部變量是在函數內部定義,但生命期卻隨函數的第一次被調用而產生, 隨程序的結束而結束, 靜態局部變量只能在定義該變量的函數中可見。
函數調用機制是由棧操作的過程實現的。函數可以遞歸調用。函數定義不能放在任何函數定義的里面。
內聯函數是為了提高編程效率而實現的, 它克服了用#define宏定義所帶來的弊病。
函數重載允許用同一個函數名定義多個函數。連接程序會根據傳遞給函數的參數數目、類型和順序調用相應的函數。函數重載使程序設計簡單化,程序員只要記住一個函數名,就可以完成一系列相關的任務。
在函數定義中通過賦值運算,即可指定默認參數值。一旦程序在調用函數時默認了參數值, 函數就使用默認參數值。 不允許在參數中間使用默認值。指定默認參數值可以使函數的使用更為簡單,同時也增強了函數的可重用性。