码迷,mamicode.com
首页 > 编程语言 > 详细

第9课 函数重载分析(下)与C、C++相互调用

时间:2018-08-23 02:03:00      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:\n   alt   测试   width   const   str   http   span   char   

重载与指针

下面的函数指针将保存哪个函数的地址:

技术分享图片

 

在给p赋值的时候,我们使用了func,但是这里并没有指明参数,编译器是怎么知道这个func函数指的是第一个func函数呢?

函数重载遇上指针:

  将重载函数名赋值给函数指针时

    1、根据重载规则挑选与函数指针参数列表一致的候选者

    2、严格匹配候选者的函数类型与函数指针的函数类型

 测试程序如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 int func(int x)
 5 {
 6     return x;
 7 }
 8 
 9 int func(int a, int b)
10 {
11     return a + b;
12 }
13 
14 int func(const char* s)
15 {
16     return strlen(s);
17 }
18 
19 typedef int(*PFUNC)(int a);
20 
21 
22 int main(int argc, char *argv[])
23 {
24     int c = 0;
25 
26     PFUNC p = func;
27         
28     c = p(1);   
29     
30     printf("c = %d\n", c);
31 
32     return 0;
33 }

编译运行结果如下:

技术分享图片

 

将19行的返回类型由int改为void或者double,再次编译,结果如下:

技术分享图片

 

三个候选函数都无法匹配p的类型。因为当函数重载遇上函数指针时,编译器会严格匹配函数类型,函数类型包括返回值类型和参数类型。

重载与指针

注意:

  1、函数重载必然发生在同一个作用域中

  2、编译器需要用参数列表或函数类型进行函数选择

  3、无法直接通过函数名得到重载函数的入口地址

 在上一节中,我们直接通过函数名打印了函数地址,这样的话和这里的第三条不就矛盾了吗?

上一节我们对函数名进行了一些转换,如果不转换的话,编译会报错,如下:

技术分享图片

 

编译错误提示我们函数指针没有上下文类型信息。

写上类型转换信息,再次编译,如下:

技术分享图片

 

因为有了明确的类型转换信息,编译器就会根据要转换的目标类型,严格的去匹配函数。严格的匹配就是根据函数的返回值类型和参数类型去匹配,这两个合起来就叫做函数类型。我们也可以说严格的按照函数类型去匹配。

 

C和C++相互调用:

技术分享图片

 C++调用C语言写的库:

C++编译器直接编译C语言源码可以直接通过,但是这里我们解决的不是源码编译问题,而是,我们要在C++中利用以前别人别写好的C库函数,这些函数是看不到源码的,它们被编译成了目标文件,我们只能调用。

示例:

编写add.h文件:

1 int add(int a, int b);

编写add.c文件:

 1 #include "add.h"
 2 
 3 
 4 
 5 int add(int a, int b)
 6 
 7 {
 8 
 9     return a + b;
10 
11 }

通过命令gcc -c add.c -o add.o将add.c编译成add.o中间文件。

在main函数中编写C++程序调用add函数(C语言编写的),如下所示:

技术分享图片

 

报错提示我们符号找不到。

 通过执行nm  add.o,我们发现add.o文件中确实有add符号。

技术分享图片

 

为了解决这种问题,我们需要强制C++编译器使用C语言的编译方式。

通过extern(extern  "C")关键字可以达到这种目的。

我们将#include "add.h"放进extern "C"中,再次编译运行,结果如下:

技术分享图片

 

 

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

我们第一个想到的是加上extern "C",但是这个关键字是C++中才有的,C语言中没有这个用法,如果我们在源程序中写上extern "C",然后用C语言编译器编译就会报错。

解决方案如下:

技术分享图片

 

__cplusplus是所有的C++编译器都支持的,标准的宏定义。

实验如下:编写C版本的main函数

技术分享图片

 

用C语言编译器可以编译成功。

注意事项:

技术分享图片

 

示例如下:

技术分享图片

 

可以看到g++编译器编译后目标名里面有参数类型信息。

 上述函数以C方式编译的话会直接报错,因为这两个函数得到相同的目标名,因为C语言中没有重载的概念。

小结:

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

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

  extern关键字能够实现C和C++的相互调用,但是extern “C”代码块中绝对不能有重载函数

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

 

第9课 函数重载分析(下)与C、C++相互调用

标签:\n   alt   测试   width   const   str   http   span   char   

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9521207.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!