【C++】 8_函數重載分析 (上)

重載的概念

  • 重載(Overload)編程

    • 同一個標識符在不一樣的上下文有不一樣的意義

如:函數

  1. "洗"和不一樣的詞彙搭配後有不一樣的含義: 洗衣服,洗臉,洗腦,洗馬桶,。。。
  2. "play"和不一樣的單詞搭配後有不一樣的含義:play chess, play piano, paly basketball,...

思考:重載在天然語言中是隨處可見的,那麼程序設計中是否也有重載呢?debug

C++ 中的函數重載(Function Overload)

  • 用同一個函數名定義不一樣的函數
  • 函數名和不一樣的參數搭配時函數的意義不一樣

編程實驗: 函數重載實驗

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

int func(int x)
{
    return x;
}

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

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

int main(int argc, char* argv[])
{
    printf("%d\n", func(3));
    printf("%d\n", func(4, 5));
    printf("%d\n", func("D.T.Software"));

    return 0;
}
輸出:
3
9
12
  • 函數重載至少知足下面的一個條件設計

    • 參數個數不一樣
    • 參數類型不一樣
    • 參數順序不一樣
int func(int a, const char* s)
{
    return a;
}

int func(const char* s, int a)
{
    return strlen(s);
}
  • 當函數默認參數趕上函數重載會發生什麼?

編程實驗: 函數默認參數 VS 函數重載

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

int func(int a, int b, int c = 0)
{
    return a * b * c;
}

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

int main(int argc, char* argv[])
{
    int c = func(1, 2);

    return 0;
}
輸出:【兩函數均可單獨匹配,致使匹配出現二義性】
error: call of overloaded ‘func(int, int)’ is ambiguous
candidates are: int func(int, int, int)
note:                 int func(int, int)
  • 編譯器調用重載函數的準則code

    • 將全部同名函數做爲候選者
    • 嘗試尋找可行的候選函數ci

      • 精準匹配實參
      • 經過默認參數可以匹配實參
      • 經過默認類型轉換匹配實參
    • 匹配失敗編譯器

      • 最終尋找到的候選函數不惟一,則出現二義性,編譯失敗
      • 沒法匹配全部候選者,函數未定義,編譯失敗
  • 函數重載的注意事項string

    • 重載函數在本質上是互相獨立的不一樣函數
    • 重載函數的函數類型不一樣
    • 函數返回值不能做爲函數重載的依據

函數重載由函數名和參數列表決定!it

編程實驗: 函數重載的本質

#include <stdio.h>

int add(int a, int b)         // int(int, int)
{
    return a + b;
}

int add(int a, int b, int c)  // int(int, int, int)
{
    return a + b + b;
}

int main()
{
    printf("%p\n", (int(*)(int, int))add);
    printf("%p\n", (int(*)(int, int, int))add);

    return 0;
}
輸出:
00871005
0087100F

vc2010編譯器符號表:io

File Type: COFF OBJECT

COFF SYMBOL TABLE
000 00AB766F ABS    notype       Static       | @comp.id
001 00000001 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   30, #relocs    0, #linenums    0, checksum        0
004 00000000 SECT2  notype       Static       | .debug$S
    Section length  4F8, #relocs    0, #linenums    0, checksum        0
006 00000000 SECT3  notype       Static       | .rdata
    Section length    8, #relocs    0, #linenums    0, checksum C59740A9
008 00000000 SECT3  notype       Static       | $SG5270
009 00000004 SECT3  notype       Static       | $SG5275
00A 00000000 SECT4  notype       Static       | .text
    Section length    B, #relocs    0, #linenums    0, checksum D0372BF8, selection    1 (pick no duplicates)
00C 00000000 SECT5  notype       Static       | .debug$S
    Section length   DC, #relocs    5, #linenums    0, checksum        0, selection    5 (pick associative Section 0x4)
00E 00000000 SECT4  notype ()    External     | ?add@@YAHHH@Z (int __cdecl add(int,int))
00F 00000000 SECT6  notype       Static       | .rtc$TMZ
    Section length    4, #relocs    1, #linenums    0, checksum        0, selection    5 (pick associative Section 0x4)
011 00000000 SECT6  notype       Static       | __RTC_Shutdown.rtc$TMZ
012 00000000 UNDEF  notype ()    External     | __RTC_Shutdown
013 00000000 SECT7  notype       Static       | .rtc$IMZ
    Section length    4, #relocs    1, #linenums    0, checksum        0, selection    5 (pick associative Section 0x4)
015 00000000 SECT7  notype       Static       | __RTC_InitBase.rtc$IMZ
016 00000000 UNDEF  notype ()    External     | __RTC_InitBase
017 00000000 SECT8  notype       Static       | .text
    Section length    E, #relocs    0, #linenums    0, checksum 3E69ABE4, selection    1 (pick no duplicates)
019 00000000 SECT9  notype       Static       | .debug$S
    Section length   E8, #relocs    5, #linenums    0, checksum        0, selection    5 (pick associative Section 0x8)
01B 00000000 SECT8  notype ()    External     | ?add@@YAHHHH@Z (int __cdecl add(int,int,int))
01C 00000000 SECTA  notype       Static       | .text
    Section length   48, #relocs    9, #linenums    0, checksum 8A8FE64F, selection    1 (pick no duplicates)
01E 00000000 SECTB  notype       Static       | .debug$S
    Section length   F0, #relocs    9, #linenums    0, checksum        0, selection    5 (pick associative Section 0xA)
020 00000000 SECTA  notype ()    External     | _main
021 00000000 UNDEF  notype       External     | __imp__printf
022 00000000 UNDEF  notype ()    External     | __RTC_CheckEsp
023 00000000 SECTC  notype       Static       | .debug$T
    Section length   50, #relocs    0, #linenums    0, checksum        0

String Table Size = 0x8A bytes

  Summary

         7AC .debug$S
          50 .debug$T
          30 .drectve
           8 .rdata
           4 .rtc$IMZ
           4 .rtc$TMZ
          61 .text

函數編譯後對應的標識符

00E 00000000 SECT4  notype ()    External     | ?add@@YAHHH@Z (int __cdecl add(int,int))
01B 00000000 SECT8  notype ()    External     | ?add@@YAHHHH@Z (int __cdecl add(int,int,int))
  1. 函數地址不一樣
  2. 編譯器編譯後函數所獲得的標識符不一樣

==> 重載函數在本質上是互相獨立的不一樣函數

小結

  • 函數重載是 C++ 中引入的概念
  • 函數重載用於模擬天然語言中的詞彙搭配
  • 函數重載使得 C++ 具備更豐富的語義表達能力
  • 函數重載的本質爲互相獨立的不一樣函數
  • C++ 中經過函數名和函數參數肯定函數調用

以上內容參考狄泰軟件學院系列課程,請你們保護原創!

相關文章
相關標籤/搜索