温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

c++中怎么实现重载函数

发布时间:2021-06-21 18:47:12 阅读:335 作者:Leah 栏目:大数据
C++开发者专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

今天就跟大家聊聊有关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.ctest5.c:8:5error: 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:5error: 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.cpptest5.cpp: In function ‘int main(int, char**)’:test5.cpp:16:22error: call of overloaded ‘func(intint)’ is ambiguous     int c = func(1, 2);                      ^test5.cpp:16:22: note: candidates are:test5.cpp:3:5: note: int func(intintint) int func(int a, int b, int c = 0)     ^test5.cpp:8:5: note: int func(intint) 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.out0x40052d0x400541
 

从输出结果我们可以看出这两个函数的入口地址不一样,这表明这两个函数是不同的函数。

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.outc=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.cpptest5.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.croot@txp-virtual-machine:/home/txp/add# vim add.hroot@txp-virtual-machine:/home/txp/add# gcc -c add.c -o add.oroot@txp-virtual-machine:/home/txp/add# lsadd.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.o0000000000000000 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.outc = 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.oroot@txp-virtual-machine:/home/txp/add# nm -s test.o0000000000000000 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.oroot@txp-virtual-machine:/home/txp/add# ./a.outc=5
 

3、如何保证一段c代码只会以c的方式被编译?

解决方法如下:

  • __cplusplus是c++编译器内置的标准宏定义

  • __cplusplus的意义,确保c代码以统一的c方式被编译成目标文件

#ifdef __cplusplusextern "C"{  #endif  #ifdef __cplusplus}#endif
 

这里把main.cpp改成:

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

输出结果:

root@txp-virtual-machine:/home/txp/add# g++ main.cpp add.oroot@txp-virtual-machine:/home/txp/add# ./a.outc = 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.ooroot@txp-virtual-machine:/home/txp/add# nm test.oo0000000000000000 T _Z3addii0000000000000014 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.oomain.cpp: In function ‘int add(intintint)’:main.cpp:8:29: error: declaration of C function ‘int add(intintint)’ conflicts with int add(int a, int b , int c)                             ^main.cpp:3:5: error: previous declaration ‘int add(intint)’ here int add(int a, int b)
 

目标名起冲突所以报错。

5、小结:

  • 函数重载是c++对c的一个重要升级

  • 函数重载通过参数列表区分不同的同名函数

  • extern关键字能够实现c和c++的相互调用

  • 编译方式决定符号表中的函数名的最终目标名

本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

看完上述内容,你们对c++中怎么实现重载函数有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://my.oschina.net/u/4065875/blog/4480914

c++
AI

开发者交流群×