C++ 函數 函數的重載 有默認參數的函數


函數的重載

 

C++允許用同一函數名定義多個函數,這些函數的參數個數和參數類型不同。這就是函數的重載(function overloading)。

 

int max1(int a,int b, int c);
double max2(double a,double b,double c);
long  max3(long a,long b,long c);

 

#include <iostream>
using namespace std;
int main( )
{
        int max(int a,int b,int c);              //函數聲明
         int max(int a,int b);                    //函數聲明
         int a=8,b=-12,c=27;
         cout<<″max(a,b,c)=″<<max(a,b,c)<<endl;   
         cout<<″max(a,b)=″<<max(a,b)<<endl;     }
    int max(int a,int b,int c)         //求3個整數中的最大者
    {
        if(b>a) a=b;
        if(c>a) a=c;
         return a;
    }
    int max(int a,int b)               //求兩個整數中的最大者
    {
        if(a>b) return a;
        else return b;
    }

參數的個數和類型可以都不同。但不能只有函數的類型不同而參數的個數和類型相同。

也就是說重載與否是由參數決定的,而不是返回值決定!!!

這里引入一個概念

函數簽名:函數的名稱及其參數類型組合在一起,就定義了一個唯一的特性,稱為函數簽名。(不包括返回類型)

c++要求重載函數具有不同的簽名。返回類型不是函數簽名的一部分。

C++ requires that overloaded functions have distinct signature.The return type is not part of a function’s signature.


例如:

int main()
{
    int f(int);
    long f(int); // error C2556: “long f(int)”: 重載函數與“int f(int)”只是在返回類型上不同
    void f(int); // error C2556: “void f(int)”: 重載函數與“int f(int)”只是在返回類型上不同
    return 0;
}

下面介紹重載中的二義性問題:

如果兩個不同寬度的數據類型進行運算時,編譯器會盡可能地在不丟失數據的情況下將它們類型統一。若float和double運算時,如果不顯式地指定為float型,會自動轉換成double型進行計算。一個整數類型int和一個浮點類型float運算時,如果不顯式地指定為int型,C++會先將整數轉換成浮點數。

int main()
{
    float x = 2.1f;
    float y = 2.1;   //warning C4305: “初始化”: 從“double”到“float”截斷
    return 0;
}

上述 語句中float y=2.1 我們以為它是一個float類型,但編譯器卻把它認為是double(因為小數默認是double型),所以給出了警示信息,一般要定義float類型,則應該改成2.1f。

通常編譯器會按照返回類型、參數類型、參數數量區 區別調用哪個重載函數,但有時候,數據類型自動轉換機制會使編譯器進入死胡同。

float fun(float a);
double fun(double a);
int main()
{
    float x;
    x = fun(5.1);
    x = fun(5);   // error C2668: “fun”: 對重載函數的調用不明確
    return 0;
}

在這里編譯器不知道應該講x=fun(5)轉換成float還是double。

 有默認參數的函數

一般情況下,在函數調用時形參從實參那里取得值,因此實參的個數應與形參相同。C++允許在定義函數時給其中的某個或某些形式參數指定默認值,這樣,當發生函數調用時,如果省略了對應位置上的實參的值時,則在執行被調函數時,以該形參的默認值進行運算。有時多次調用同一函數時用同樣的實參,給形參一個默認值,這樣形參就不必一定要從實參取值了。如有一函數聲明
      

  float area(float r=6.5);
  area( );              //相當於area(6.5);


如果不想使形參取此默認值,則通過實參另行給出

 area(7.5);            //形參得到的值為7.5,而不是6.5

實參與形參的結合是從左至右順序進行的。因此指定默認值的參數必須放在形參表列中的最右端,否則出錯。例如:

void fun1(float a,int b=0int c,char d=’a’);     //不正確
void fun2(float a,int c,int b=0, char d=’a’);     //正確

在使用帶有默認參數的函數時有兩點要注意:
(1)如果函數的定義在函數調用之前,則應在函數定義中給出默認值。如果函數的定義在函數調用之后,則在函數調用之前需要有函數聲明,此時必須在函數聲明中給出默認值,在函數定義時可以不給出默認值。
(2)一個函數不能既作為重載函數,又作為有默認參數的函數。因為當調用函數時如果少寫一個參數,系統無法判定是利用重載函數還是利用默認參數的函數,出現二義性,系統無法執行。

void fun(int);            //重載函數之一
void fun(intint = 2);     //重載函數之二,帶有默認參數
void fun(int = 1int = 2);  //重載函數之三,帶有默認參數
fun(3);    //error: 到底調用3個重載函數中的哪個?
fun(4,5)   //error:到底調用后面2個重載函數的哪個?

 

 默認參數一般在函數聲明中提供。如果程序中既有函數的聲明又有函數的定義時,則定義函數時不允許再定義參數的默認值。

void  fun(int x = 0,int y = 0);
void main() {}
void fun(int x = 0, int y = 0) { } 
// error C2572: “fun”: 重定義默認參數 : 參數 2
// error C2572: “fun”: 重定義默認參數 : 參數 1

默認值可以是全局變量、全局常量,甚至是一個函數。例如:

int a=1int fun(int);
int g(int x;fun(a)); //OK,允許默認值為函數

默認值不可以是局部變量,因為默認參數的函數調用是在編譯時確定的,而局部變量的位置與值在編譯時均無法確定。

例如:

int main()
{
    int i;
    void g(int x=i);  // error C2587: “i”: 非法將局部變量作為默認參數
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM