C++ 重載函數


1、什么是重載函數

  同一個函數名定義不同的函數,當函數名相同,不同的參數搭配時含義不同。

  例如:

  

#include <stdio.h>
#include <string.h>


int func(int x)
{
    return x;
}

int func(int x,int y)
{
    return x + y;
}

int func(const char *s)
{
    return strlen(s);
}



int main(int argc, char *argv[])
{
    printf("Begin...\n");
    printf("%d\n" ,func(1));
    printf("%d\n" ,func(2,3));
    printf("%d\n" ,func("abcdefg"));
    printf("End...\n");
    return 0;
}

  運行結果:

Begin...
1
5
7
End...

 

  上面代碼函數名相同,在C語言中是肯定會報錯的因為C語言不支持重載函數。而在C++中是不會報錯的。而且會根據參數 調用 對應的函數。

 

2、允許重載的條件是什么了?

  2.1、參數類型不同

  2.2、參數個數不同

  2.3、參數順序不同

  三個條件滿足其中一條即可滿足重載。

  例如:下面代碼中的兩個 func 就滿足第 2.3條 參數順序不同  

#include <stdio.h>
#include <string.h>

int func(const char *s ,int a)
{
    return a;
}

int func(int a,const char *s )
{
    return strlen(s);
}


int main(int argc, char *argv[])
{
    printf("Begin...\n");
    printf("%d\n",func("abc",2));
    printf("%d\n",func(2,"abc"));
        printf("End...\n");
        return 0;
}

  運行結果:

Begin...
2
3
End...

 

3、編譯器調用重載的准則:

  3.1、將所有同名的函數作為候選

  3.2、嘗試尋找可行的候選參數

    3.2.1、精確匹配實參

    3.2.2、通過默認參數能夠匹配實參

    3.2.3、通過默認類型轉換匹配實參

匹配失敗的原因:

  1、最終找出來的候選函數不唯一,出現二義性,編譯失敗。

  例如:這里調用 printf("%d\n" func(1,2)); 的時候 就有兩個條件可以匹配所以編譯器也不知道應該調用那個函數。

#include <stdio.h>
#include <string.h>

int func(int a,int b)
{
    return a + b;
}

int func(int a,int b,int c=10)
{
    return a+b+c;
}


int main(int argc, char *argv[])
{
    printf("Begin...\n");
    printf("%d\n" func(1,2));
        printf("End...\n");
        return 0;
}

 編譯結果: 

test.cpp:18:25: error: call of overloaded ‘func(int, int)’ is ambiguous
  printf("%d\n" ,func(1,2));
                         ^
test.cpp:4:5: note: candidate: int func(int, int)
 int func(int a,int b)
     ^~~~
test.cpp:9:5: note: candidate: int func(int, int, int)
 int func(int a,int b,int c=10)
     ^~~~

 

  2、無法匹配所有候選者,函數未定義,編譯失敗

4、函數重載的注意事項。

  4.1、重載函數在本質上是相互獨立的函數

  4.2、重載函數的函數類型不同

  4.3、函數返回值不能作為函數重載的依據

 函數重載是由函數名 和參數列表決定的。    

 

5、重載與指針。

  如下代碼:

 

#include <stdio.h>
#include <string.h>

int func(int a,int b)
{
    return a + b;
}

int func(int a,int b,int c=10)
{
    return a+b+c;
}

int func(const char *s)
{
    return strlen(s);
}    

typedef int (*Pfunc) (int a,int b);

int main(int argc, char *argv[])
{
    printf("Begin...\n");
    Pfunc P= func;
    int c = 0;
    c = P(1,2);
    printf("c = %d\n",c);
    printf("End...\n");
    return 0;
}

  運行結果:

Begin...
c = 3
End...

  通過運行結果 可以清楚的看出, c = P(1,2);    其實就是調用到  int func(int a,int b)    這個函數。

  使用  typedef int (*Pfunc) (int a,int b);  定義了一個 函數指針。

  隨后通過  Pfunc P= func;   對函數指針 P進行初始化。

  調用 c = P(1,2); 

  在這個過程中 C++通過   typedef int (*Pfunc) (int a,int b);  定義的類型使得 Pfunc P= func; 這個初始化能夠正確的匹配到  int func(int a,int b)   這個函數。

  最終調用到 int func(int a,int b)   這個函數。

  所以將重載函數名賦值給函數指針的時候

    1、根據重載規則挑選與函數參數列表一致的候選者。

    2、嚴格匹配候選者的函數類型與指針的函數類型。

  上面說過 函數的 重載 與 返回值  無關,但是在通過函數指針指向重載函數的時候,C++會將返回值也作為編譯器判斷語法是否錯誤的依據。(這里就對應了上面第二點說的嚴格匹配候選者,包括匹配 返回值、函數名、函數參數)

  注意:

  1、只有在同一個作用域中函數才能重載。

  2、編譯器選擇函數的 依據是 函數列表 函數參數

  3、無法通過函數名直接得到重載函數的入口地址。(可以通過強制類型轉換的到函數的入口地址,需要給編譯器提供足夠多的信息選擇到對應函數)

    例如:printf("%p\n",(int(*)(int,int))func);   

 


免責聲明!

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



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