中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

c++中怎么實現重載函數

發布時間:2021-06-21 18:47:12 來源:億速云 閱讀:321 作者:Leah 欄目:大數據

今天就跟大家聊聊有關c++中怎么實現重載函數,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。


一、C++中的函數重載:

1、函數重載的概念:

  • 用同一個函數名定義不同的函數

  • 當函數名和不同的參數搭配時函數的含義不同

  • 注意:在c語言中是沒有函數重載這個概念的。

代碼示例演示:

#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()
{

   return 0;

}

 

上面在c++編譯器里面編譯時沒有問題的,如果放在c語言編譯器里面編譯是會報錯的:

root@txp-virtual-machine:/home/txp# gcc test5.c
test5.c:8:5: error: conflicting types for ‘func’
 int func(int a, int b)
     ^
test5.c:3:5: note: previous definition of ‘func’ was here
 int func(int x)
     ^
test5.c:13:5: error: conflicting types for ‘func’
 int func(const char* s)
     ^
test5.c:3:5: note: previous definition of ‘func’ was here
 int func(int x)

 

所以說c語言里面不支持函數重載。

2、函數重載至少要滿足下面的一個條件:

  • 參數個數不同

  • 參數類型不同

  • 參數順序不同

比如下面兩個函數可以構造重載函數嗎?

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

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

答案肯定是可以構造重載函數的,讀者可以自己試試(這個比較好理解)。

3、當函數默認參數遇上函數重載會發生什么?

例如下面的兩個函數:

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

 

到底會發生啥,我們還是看下面這個實驗:

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

 

運行結果:

root@txp-virtual-machine:/home/txp# g++ test5.cpp
test5.cpp: In function ‘int main(int, char**)’:
test5.cpp:16:22: error: call of overloaded ‘func(int, int)’ is ambiguous
     int c = func(1, 2);
                      ^
test5.cpp:16:22: note: candidates are:
test5.cpp:3:5: note: int func(int, int, int)
 int func(int a, int b, int c = 0)
     ^
test5.cpp:8:5: note: int func(int, int)
 int func(int a, int b)

 

從上面報錯的結果里面有一個單詞ambiguous(意思是夢棱兩可的),也就是說默認參數這種使用時不允許的。

4、C++編譯器調用重載函數的準則:

  • 將所有同名函數作為候選者

  • 嘗試尋找可行的候選函數:

  • 精確匹配實參

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

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

  • 匹配失敗:

      最終尋找到的候選函數不唯一,則出現二義性,編譯失敗

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

5、函數重載的注意事項:

  • 重載函數在本質上是相互獨立的不同函數

  • 重載函數的函數類型不同

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

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

代碼測試:

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

運行結果:

root@txp-virtual-machine:/home/txp# ./a.out
0x40052d
0x400541

 

從輸出結果我們可以看出這兩個函數的入口地址不一樣,這表明這兩個函數是不同的函數。

6、小結:

  • 函數重載是c++中引入的概念

  • 函數重載的本質是相互獨立的不同函數

  • c++中通過函數名和函數參數確定函數調用

二、重載函數進階學習

1、重載與指針:

下面的函數指針將保存哪個函數的地址?

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 c =0;

PFUNC p = func;

c = p(2)//到底選擇哪個func函數

 

函數重載遇上函數指針:

  • 將函數名賦值給函數指針時

  • 根據重載規則跳線與函數指針參數列表一致的候選者

  • 嚴格匹配候選者的函數類型與函數指針的函數類型

代碼試驗:

#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(2);
     printf("c=%d\n",c);
     return 0;
}

 

輸出結果:

root@txp-virtual-machine:/home/txp# ./a.out
c=2

 

從輸出結果來看,很明顯調用了第一個func函數。

2、注意:

  • 函數重載必然發生在同一個作用域中

  • 編譯器需要用參數列表或者函數類型進行函數選擇(也就是說碰到指針,要注意函數類型了)

無法直接通過函數名得到重載函數的入口地址,這里還是通過上面的例子演示一下:

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

輸出結果:

root@txp-virtual-machine:/home/txp# g++ test5.cpp
test5.cpp: In function ‘int main()’:
test5.cpp:15:23: error: overloaded function with no contextual type information
     printf("%p\n", add);
                       ^
test5.cpp:16:23: error: overloaded function with no contextual type information
     printf("%p\n", add);

 

三、C++和C相互調用:

  • 實際工程中C++和c代碼相互調用是不可避免的

  • c++編譯器能夠兼容c語言的編譯方式

  • c++編譯器會優先使用c++編譯的方式

extern關鍵字能夠強制讓C++編譯器進行c方式的編譯:

extern "c"
{


}

 

1、下面進行一個c++中調用c函數,這里我在當前創建三個文件:add.c 、add.h 、main.cpp。內容分別如下:

add.c內容:


#include "add.h"
int add(int a, int b)

{

    return a + b;

}

 

add.h內容:

int add(int a, int b);
 

然后我用gcc編譯編譯生成add.o文件:

root@txp-virtual-machine:/home/txp/add# vim add.c
root@txp-virtual-machine:/home/txp/add# vim add.h
root@txp-virtual-machine:/home/txp/add# gcc -c add.c -o add.o
root@txp-virtual-machine:/home/txp/add# ls
add.c  add.h  add.o

 

然后main.cpp里面調用add.c

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

輸出結果:

root@txp-virtual-machine:/home/txp/add# g++ main.cpp add.o
/tmp/ccqz3abQ.o: In function `main':
main.cpp:(.text+0x13): undefined reference to `add(int, int)'
collect2: error: ld returned 1 exit status


 

結果顯示找不到這個函數,為了能夠在c++里面調用c語言里面的函數,我們就要使用剛才上面講的第四點了;這里我們先用nm命令來查看一下add.o文件里面是否生成符號表(有生成):

root@txp-virtual-machine:/home/txp/add# nm add.o
0000000000000000 T add

 

解決方法,main.cpp改成:

#include <stdio.h>

extern "c"
{
    #include "add.h"

}


int main()
{
    int c = add(1, 2);
    
    printf("c = %d\n", c);

    return 0;
}

 

輸出結果:

root@txp-virtual-machine:/home/txp/add# ./a.out
c = 3

 

2、c中如何調用c++函數:

這里我把main.cpp的內容改成:

extern "C"
{
   int add(int a, int b);

}

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


 

編譯輸出:

root@txp-virtual-machine:/home/txp/add# g++ -c main.cpp -o test.o
root@txp-virtual-machine:/home/txp/add# nm -s test.o
0000000000000000 T add


 

add.c文件內容改成:

#include <stdio.h>
int main()

     int c =0;
     c = add(2,3);
     printf("c=%d\n",c);
     return 0;
}
 

輸出結果:

root@txp-virtual-machine:/home/txp/add# gcc add.c test.o
root@txp-virtual-machine:/home/txp/add# ./a.out
c=5

 

3、如何保證一段c代碼只會以c的方式被編譯?

解決方法如下:

  • __cplusplus是c++編譯器內置的標準宏定義

  • __cplusplus的意義,確保c代碼以統一的c方式被編譯成目標文件

#ifdef __cplusplus
extern "C"
{
  #endif

  #ifdef __cplusplus
}
#endif
 

這里把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;
}
 

輸出結果:

root@txp-virtual-machine:/home/txp/add# g++ main.cpp add.o
root@txp-virtual-machine:/home/txp/add# ./a.out
c = 3

 

4、注意事項

  • C++編譯器不能以c的方式編譯重載函數

  • 編譯方式決定函數名被編譯后的目標名

  • c++編譯方式將函數名和參數列表編譯成目標名,這里舉個例子main.cpp:

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

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

編譯輸出:

root@txp-virtual-machine:/home/txp/add# g++ -c main.cpp -o test.oo
root@txp-virtual-machine:/home/txp/add# nm test.oo
0000000000000000 T _Z3addii
0000000000000014 T _Z3addiii

 

說明ii表示兩個參數,iii表示三個參數

  • c編譯方式只將函數名作為目標名進行編譯,這里還是以main.cpp為例:

extern "C"
{
   int add(int a, int b)
  {
       return a+b;
  }

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

 

輸出結果:

root@txp-virtual-machine:/home/txp/add# g++ -c main.cpp -o test.oo
main.cpp: In function ‘int add(int, int, int)’:
main.cpp:8:29: error: declaration of C function ‘int add(int, int, int)’ conflicts with
 int add(int a, int b , int c)
                             ^
main.cpp:3:5: error: previous declaration ‘int add(int, int)’ here
 int add(int a, int b)

 

目標名起沖突所以報錯。

5、小結:

  • 函數重載是c++對c的一個重要升級

  • 函數重載通過參數列表區分不同的同名函數

  • extern關鍵字能夠實現c和c++的相互調用

  • 編譯方式決定符號表中的函數名的最終目標名

本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

看完上述內容,你們對c++中怎么實現重載函數有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

手游| 五河县| 汤原县| 兴义市| 建水县| 赣州市| 呼伦贝尔市| 奇台县| 陆丰市| 双鸭山市| 黎城县| 九龙县| 邢台市| 肇源县| 定日县| 体育| 宁都县| 嘉祥县| 宜昌市| 开远市| 略阳县| 八宿县| 隆子县| 盈江县| 普格县| 广水市| 扬州市| 长白| 砚山县| 芜湖县| 保德县| 区。| 内江市| 波密县| 任丘市| 华蓥市| 株洲县| 古浪县| 汝州市| 富平县| 色达县|