1. 程式人生 > >C++過載函式

C++過載函式

C++允許在同一範圍中宣告幾個功能類似的同名函式,但是這些同名函式的形式引數(指引數的個數、型別或者順序)必須不同,即函式的引數列表不同,也就是說用同一個運算子完成不同的運算功能。這就是過載函式。過載函式常用來實現功能類似而所處理的資料型別不同的問題。

函式過載有什麼好處?
過載函式通常用來命名一組功能相似的函式,這樣做減少了函式名的數量,避免了名字空間的汙染,對於程式的可讀性有很大的好處。當函式的編寫者充分考慮了不同情況下應該執行稍有不同的函式,函式的使用者就不必為這些小細節而煩惱了。
類的建構函式跟類名相同,也就是說:建構函式都同名。如果沒有函式過載機制,要想例項化不同的物件,那是相當的麻煩!

例:
void print(int a)
{
    printf("void print(int a)\n");
}

void print(string a) //引數型別不一樣
{
printf("void print(string a)\n");
}

上面兩個就是過載的函式。呼叫函式時,通過對引數的識別從而呼叫不同的過載函式。例如在main函式中,如果給的引數是int,那麼就會呼叫上面的那個過載函式,如果給的引數是string,那麼就會呼叫下面的過載函式。

此外,引數個數和順序不同也能構成不同的過載函式。例:

void print(int a ,string b); //引數個數不同
void print(string a ,int b);//引數順序不同

所以,構成函式過載的條件如下:
1、函式名相同。
2、這些同名函式的形式引數(指引數的個數、型別或者順序)必須不同,即引數列表不同。

需要注意的是,返回值型別不同不構成過載函式。例:

char print(int a ,string b ,string b);
double print(double a);
//這兩個函式和以上的print函式都不是過載函式

過載函式的匹配原則:
1、嚴格匹配,找到後就呼叫。
2、沒有找到嚴格匹配的函式,但是可以通過隱式轉化,找到適合的過載函式。
例:

#include<iostream>
#include<stdio.h> using namespace std; void count(int a) //引數型別為int { cout << "void count(int a)" << endl; } void count(string a)//引數型別 { cout << "void count(string a)" << endl; } int main() { double min = 0.5; count(min); //實參為double型別 getchar(); return 0; }

通過隱式轉換可以將double轉為int,然後呼叫引數型別為int 的函式。
但是要注意一個問題,就是隱式轉換的規則
而且要注意int到long和double,double到int和float的隱式轉換,會引發二義性(ambiguous)。就是有兩個都可行的選擇,計算機無法替你做選擇。(計算機也有選擇困難症啊。。。。)例:

#include<iostream>
#include<stdio.h>
using namespace std;
void count(double a)//形參型別為double
{
    cout << "void count(double a)" << endl;
}
void count(long b)//形參型別為long
{
    cout << "void count(long b)" << endl;
}
int main()
{
    int min = 10;
    count(min);//實參型別為int
    getchar();
    return 0;
}

此時無法通過編譯。顯示 error C2668: “count”: 對過載函式的呼叫不明確。即,ambiguous。

下面簡單說說函式過載的原理
C++採用命名傾軋(name mangling)的技術來改變同名函式,以區分引數不同的函式。
例:
void name(char a);通過傾軋->變成類似於void name_c;的形式。
void name(string a);通過傾軋->變成類似於void name_s;的形式。
void name(char a, int b);通過傾軋->變成類似於void name_ci;的形式。

name mangling 發生在兩個階段,一個是.cpp編譯時,一個是.h的宣告階段。只有兩個階段同時進行才能匹配上。也就是要同時改名才可以。

具體的可參照其他大神部落格: