欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++超詳細(xì)分析函數(shù)重載的使用

 更新時間:2022年04月20日 16:50:35   作者:清風(fēng)自在?流水潺潺  
C++?允許多個函數(shù)擁有相同的名字,只要它們的參數(shù)列表不同就可以,這就是函數(shù)的重載(Function?Overloading),借助重載,一個函數(shù)名可以有多種用途

一、函數(shù)重載分析(上)

1.1 重載的定義

定義:同一個標(biāo)識符在不同的上下文有不同的意義

1.2 函數(shù)重載的定義

  • 用同一個函數(shù)名定義不同的函數(shù)
  • 當(dāng)函數(shù)名和不同的參數(shù)搭配時函數(shù)的含義不同

如下:

下面看一段代碼,感受一下:

#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;
}

下面為輸出結(jié)果:

1.3 函數(shù)重載需要滿足的條件

函數(shù)重載至少滿足下面的一個條件:

  • 參數(shù)個數(shù)不同
  • 參數(shù)類型不同
  • 參數(shù)順序不同

下圖所示就是參數(shù)的順序不同:

下面看一個函數(shù)默認(rèn)參數(shù)遇上函數(shù)重載的實(shí)例程序:

#include <stdio.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;
}

下面為輸出結(jié)果:

編譯報(bào)錯,因?yàn)槟@鈨煽?。如果說調(diào)用第一個函數(shù)說的過去,因?yàn)榉虾瘮?shù)默認(rèn)參數(shù)規(guī)則,c 的值已經(jīng)確定;調(diào)用第二個函數(shù)也符合常理,所以編譯不會通過。

1.4 編譯器調(diào)用重載函數(shù)的準(zhǔn)則

將所有同名函數(shù)作為候選者

嘗試尋找可行的候選函數(shù)

  • 精確匹配實(shí)參
  • 通過默認(rèn)參數(shù)能夠匹配實(shí)參
  • 通過默認(rèn)類型轉(zhuǎn)換匹配實(shí)參

匹配失敗

  • 最終尋找到的候選函數(shù)不唯一,則出現(xiàn)二義性,編譯失敗。
  • 無法匹配所有候選者,函數(shù)未定義,編譯失敗。

1.5 函數(shù)重載的注意事項(xiàng)

  • 重載函數(shù)在本質(zhì)上是相互獨(dú)立的不同函數(shù)
  • 重載函數(shù)的函數(shù)類型不同
  • 函數(shù)返回值不能作為函數(shù)重載的依據(jù)

函數(shù)重載是由函數(shù)名和參數(shù)列表決定的?。?!

函數(shù)重載的本質(zhì)是什么?下面通過一段代碼深入分析,編譯環(huán)境為VS2012。

#include "stdafx.h"
#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 + c;
}
int main()
{
    printf("%p\n", (int(*)(int, int))add);
    printf("%p\n", (int(*)(int, int, int))add);
    return 0;
}

由C語言的知識可以知道,函數(shù)名就是函數(shù)的入口地址,所以輸出結(jié)果如下:

可以看到,兩個 add() 函數(shù)的入口地址不一樣,所以這兩個 add 是兩個不同的函數(shù)。

編譯器是如何看待這兩個 add() 函數(shù)的呢?下面來深入分析。先看一下編譯器產(chǎn)生的中間結(jié)果,在Test -> Debug -> Test.obj 文件中。

然后使用VS2012里面自帶的命令行工具查看 Test.obj 里面有什么東西。

上圖示為VS2012 命令行所在位置

輸入 dumpbin,如下:

這里只需要關(guān)系 SYMBOLS(符號表),符號表就是編譯器在編譯過程中根據(jù)源代碼所生成的一張表,這張表有程序的函數(shù)名變量等等。

輸入以下命令,其中 /symbols 后面為 Test.obj 所在的位置。

找到下面的地方,可以看到編譯器編譯 (int __cdecl add(int,int)) 時標(biāo)識符為?add@@YAHHH@Z;而編譯器編譯(int __cdecl add(int,int,int)) 時標(biāo)識符為?add@@YAHHHH@Z ,也就是說編譯器在編譯這兩個函數(shù)時已經(jīng)把這兩個函數(shù)分別對待,盡管它們名字一樣,所以兩個 add() 函數(shù)的入口地址不一樣,這就很好理解了。

1.6 小結(jié)

  • 函數(shù)重載是 C++ 中引入的概念
  • 函數(shù)重載用于模擬自然語言中的詞匯搭配
  • 函數(shù)重載使得 C++ 具有更豐富的語義表達(dá)能力
  • 函數(shù)重載的本質(zhì)為相互獨(dú)立的不同函數(shù)
  • C++ 中通過函數(shù)名和函數(shù)參數(shù)確定函數(shù)調(diào)用

二、函數(shù)重載分析(下)

2.1 函數(shù)重載遇上函數(shù)指針

將重載函數(shù)名賦值給函數(shù)指針時

  • 根據(jù)重載規(guī)則挑選與函數(shù)指針參數(shù)列表一致的候選者
  • 嚴(yán)格匹配候選者的函數(shù)類型與函數(shù)指針的函數(shù)類型

下面看一段代碼:

#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);
}
typedef int(*PFUNC)(int a);
int main(int argc, char *argv[])
{
    int c = 0;
    PFUNC p = func;
    c = p(1);   
    printf("c = %d\n", c);
    return 0;
}

下面為輸出結(jié)果:

這也就是前面說的通過函數(shù)指針?biāo)赶虻暮瘮?shù)類型參數(shù)列表來進(jìn)行選擇。

注意事項(xiàng)

  • 函數(shù)重載必然發(fā)生在同一個作用域中
  • 編譯器需要用參數(shù)列表或函數(shù)類型進(jìn)行函數(shù)選擇
  • 無法直接通過函數(shù)名得到重載函數(shù)的入口地址(可以通過指針來獲取)

如下,這段代碼想通過函數(shù)名獲取重載函數(shù)的入口地址:

#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 + c;
}
int main()
{
    printf("%p\n", add);
    printf("%p\n", add);
    return 0;
}

編譯的時候會報(bào)錯,無法確定是哪個函數(shù)。

2.2 C++和C的相互調(diào)用

  • 實(shí)際工程中C++和C代碼相互調(diào)用是不可避免的
  • C++編譯器能夠兼容C語言的編譯方式
  • C++編譯器會優(yōu)先使用C++編譯的方式
  • extern 關(guān)鍵字能強(qiáng)制讓C++編譯器進(jìn)行C方式的編譯

如下:

在 Linux環(huán)境下新建一個 9-2 文件夾,先在文件夾下新建 add.c 和 add.h 文件,如下:

add.c :

#include "add.h"
int add(int a, int b)
{
    return a + b;
}

add.h :

int add(int a, int b);

通過 linux 命令 cd 進(jìn)入 9-2 文件夾,再將 add.c 轉(zhuǎn)換成 add.o 文件,如下所示:

然后在 9-2 文件夾下建一個 main.cpp 文件,如下:

mian.cpp :

#include <stdio.h>
#include "add.h"
int main()
{
    int c = add(1,2);
    printf("c = %d\n", c);
    return 0;
}   

對程序進(jìn)行編譯,發(fā)現(xiàn)程序報(bào)錯,沒有定義 add() 函數(shù),但是函數(shù)確實(shí)已經(jīng)定義了,可以使用 linux 中的 nm 指令查看 add.o 里面的信息,打印出來的就是符號表信息,可以看到確實(shí)有 add 。

這個時候就需要使用 extern關(guān)鍵字強(qiáng)制讓C++編譯器進(jìn)行C方式的編譯,所以 main.cpp就要修改成這樣:

#include <stdio.h>
extern "C"
{
  #include "add.h"  
}
int main()
{
    int c = add(1,2);
    printf("c = %d\n", c);
    return 0;
}   

這樣編譯就能通過了:

如果在 9-2 文件中新建一個 main.c 文件,main.c 里面的代碼 與 main.cpp 中的相同。

進(jìn)行編譯,發(fā)現(xiàn)會報(bào)錯誤,因?yàn)?extern 關(guān)鍵詞寫法是 C++ 中的, C語言不支持該寫法。那有沒有一種寫法既能被 C語言編譯通過,又能讓 C++編譯通過呢?且看下面。

2.3 使得C代碼只會以C的方式被編譯的解決方案

  • _cplusplus 是C++編譯器內(nèi)置的標(biāo)準(zhǔn)宏定義
  • _cplusplus 的意義是確保C代碼以統(tǒng)一的C方式被編譯成目標(biāo)文件

如下:

所以上述代碼可以寫作,main.c和 main.cpp 均為:

#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "add.h"
#ifdef __cplusplus
}
#endif
int main()
{
    int c = add(1, 2);
    printf("c = %d\n", c);
    return 0;
}

這樣程序在 C語言和 C++ 的編譯環(huán)境下均能通過,如下:

注意事項(xiàng)

C++編譯器不能以C的方式編譯重載函數(shù)

編譯方式?jīng)Q定函數(shù)名被編譯后的目標(biāo)名

  • C++編譯方式將函數(shù)名和參數(shù)列表編譯成目標(biāo)名
  • C 編譯方式只將函數(shù)名作為目標(biāo)名進(jìn)行編譯

下面通過一個例子說明一下:

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 + c;
}

將該代碼編譯成目標(biāo)文件,取名為 test.oo,然后通過 linux 中的 nm 命令查看 test.oo 中的東西,可以看到 test 符號表里面有兩個東西 T _Z3addii 和T _Z3addiii,這就是 add 函數(shù)被編譯過后的目標(biāo)函數(shù)名,ii 表示兩個參數(shù), iii 表示三個參數(shù)。

如果采用 C 方式編譯重載函數(shù),代碼如下:

extern "C"
{
    int add(int a, int b)  // ==>add
    {
        return a + b;
    }
    int add(int a, int b, int c) // ==>add
    {
        return a + b + c;
    }
}

下面為編譯結(jié)果,可以看到編譯報(bào)錯,說兩個 add() 函數(shù)沖突了。

2.4 小結(jié)

  • 函數(shù)重載是 C++ 對 C 的一個重要升級
  • 函數(shù)重載通過函數(shù)參數(shù)列表區(qū)分不同的同名函數(shù)
  • extern 關(guān)鍵字能夠?qū)崿F(xiàn) C 和 C++的相互調(diào)用
  • 編譯方式?jīng)Q定符號表中的函數(shù)名的最終目標(biāo)名

到此這篇關(guān)于C++超詳細(xì)分析函數(shù)重載的使用的文章就介紹到這了,更多相關(guān)C++函數(shù)重載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言深入講解宏的定義與使用方法

    C語言深入講解宏的定義與使用方法

    在 C 語言中,可以采用命令 #define 來定義宏。該命令允許把一個名稱指定成任何所需的文本,例如一個常量值或者一條語句。在定義了宏之后,無論宏名稱出現(xiàn)在源代碼的何處,預(yù)處理器都會把它用定義時指定的文本替換掉
    2022-04-04
  • C++中的多態(tài)問題—理解虛函數(shù)表及多態(tài)實(shí)現(xiàn)原理

    C++中的多態(tài)問題—理解虛函數(shù)表及多態(tài)實(shí)現(xiàn)原理

    這篇文章主要介紹了C++中的多態(tài)問題—理解虛函數(shù)表及多態(tài)實(shí)現(xiàn)原理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • MFC之ComboBox控件用法實(shí)例教程

    MFC之ComboBox控件用法實(shí)例教程

    這篇文章主要介紹了MFC之ComboBox控件用法,包括了ComboBox控件常見的各類用法,非常具有實(shí)用價值,需要的朋友可以參考下
    2014-09-09
  • C++中的Z字形變換問題

    C++中的Z字形變換問題

    將一個給定字符串?s?根據(jù)給定的行數(shù)?numRows?,以從上往下、從左到右進(jìn)行?Z?字形排列,這樣一個需求怎么實(shí)現(xiàn)呢,下面小編給大家?guī)砹薈++中的Z字形變換問題,需要的朋友可以參考下
    2022-07-07
  • C++實(shí)現(xiàn)產(chǎn)生隨機(jī)數(shù)和相應(yīng)的猜拳小游戲?qū)嵗a

    C++實(shí)現(xiàn)產(chǎn)生隨機(jī)數(shù)和相應(yīng)的猜拳小游戲?qū)嵗a

    C++中沒有自帶的random函數(shù),要實(shí)現(xiàn)隨機(jī)數(shù)的生成就需要使用rand()和srand()。下面這篇文章主要給大家介紹了關(guān)于C++實(shí)現(xiàn)產(chǎn)生隨機(jī)數(shù)和相應(yīng)的猜拳小游戲的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-09-09
  • C語言中的運(yùn)算符和結(jié)合性問題

    C語言中的運(yùn)算符和結(jié)合性問題

    這篇文章主要介紹了C語言中的運(yùn)算符和結(jié)合性問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 適合初學(xué)者的C語言轉(zhuǎn)義字符講解

    適合初學(xué)者的C語言轉(zhuǎn)義字符講解

    轉(zhuǎn)義字符是很多程序語言、數(shù)據(jù)格式和通信協(xié)議的形式文法的一部分。對于一個給定的字母表,一個轉(zhuǎn)義字符的目的是開始一個字符序列,使得轉(zhuǎn)義字符開頭的該字符序列具有不同于該字符序列單獨(dú)出現(xiàn)(沒有轉(zhuǎn)義字符開頭)時的語義。因此轉(zhuǎn)義字符開頭的字符序列被叫做轉(zhuǎn)義序列
    2022-04-04
  • C++多線程編程簡單實(shí)例

    C++多線程編程簡單實(shí)例

    本文給大家分享的是C++多線程編程簡單實(shí)例,由于C++本身沒有多線程機(jī)制,在windows下我們使用調(diào)用SDK win32 api來實(shí)現(xiàn),示例都很簡單,講解的也很詳細(xì),推薦給大家。
    2015-03-03
  • 對C語言中sizeof細(xì)節(jié)的三點(diǎn)分析介紹

    對C語言中sizeof細(xì)節(jié)的三點(diǎn)分析介紹

    以下是對C語言中sizeof的細(xì)節(jié)進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以參考下
    2013-07-07
  • C++中的基類和派生類構(gòu)造函數(shù)示例詳解

    C++中的基類和派生類構(gòu)造函數(shù)示例詳解

    這篇文章主要介紹了C++的基類和派生類構(gòu)造函數(shù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09

最新評論