1、重载与指针
- 下面的函数指针将保存哪个函数的地址?
typedef int(*PFUNC)(int a)
int c = 0;
PFUNC p = func;
c = p(1);
很明显就是第一个函数。
- 函数重载遇上函数指针
— 将重载函数名赋值给函数指针时(上面的第三条语句)
1、根据重载规则挑选与函数指针参数列表一致的候选者
2、严格匹配候选者的函数类型与函数指针的函数类型
#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);
//typedef void(*PFUNC)(int a);
int main()
{
int c = 0;
PFUNC p = func;
c = p(1);
printf("c = %d\n", c);
return 0;
}
如果一旦在第17行代码改变为没有的函数类型,就会报错,所以要严格匹配。
- 注意:
— 函数重载必然发生在同一个作用域中
— 编译器需要用参数列表或函数类型进行函数选择
— 无法直接通过函数名得到重载函数的入口地址
如果不根据函数指针的类型或者参数列表,我们是得不到重载函数的地址,仅仅通过函数名根本办不到。
回顾上一章的最后一个程序,如果我们改一下代码
#include <stdio.h>
#include <string.h>
int add(int a, int b)
{
return a + b;
}
int add(int a, int b, int c)
{
return a + b + c;
}
int main()
{
printf("%p\n", add);
printf("%p\n", add);
return 0;
}
在代码的14行和15行,如果我们直接用函数名去打印函数的入口地址会出现什么情况?
很明显会出错,所以函数的重载我们不能通过函数名得到函数的入口地址。
以前C语言里面没有函数重载的概念,所以在C语言我们可以用函数名来获取函数的入口地址。
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int main()
{
printf("%p\n", add);
return 0;
}
2、C++和C相互调用
- 实际工程中C++和C代码相互调用是不可避免的
- C++编译器能够兼容C语言的编译方式
- C++编译器会优先使用C++编译器的方式
- extern 关键字能强制让C++编译器进行C方式的编译
extern "C"
{
//do C-style compilation here
}
什么情况下用extern"C"?就是我们的C++程序里面如果要加入C程序,但是C++编译器是以C++的方式把它编译出来,未免会有偏差,所以我们可以在我们想要用C方式编译的前面写上extern"C",然后用大括号扩住。
举例:在Linux C环境下,先写两个文件
add.c
#include "add.h"
int add(int a,int b)
{
return a+b;
}
add.h
int add(int a,int b);
在Linux下编译成add.0的文件
然后写一个C++程序
main.cpp
#include <stdio,h>
#include <add.h>
int main()
{
int c = add(1,2);
printf("c = %d\n",c);
return 0;
}
用命令行编译g++ main.cpp add.o,发现会报错,这是为什么呢,因为 main 文件是C++编译器用C++方式编译,但是头文件是一段C语言代码,所以我们应该把头文件用C语言的方式编译,所以:
#include <stdio.h>
extern"C"
{
#include "add.h"
}
int main()
{
int c = add(1,2);
printf("c = %d\n",c);
return 0;
}
这样就是对的。
问题:如何保证一段C代码只会以C的方式被编译?
extern"C"是C++里面独有的,C语言里面不支持extern"C"的用法。所以在C语言里面extern“C”就会报错
解决方案:
- __cplusplus是C++编译器内置的标准宏定义(C语言编译器内部没有这个宏)
- __cplusplus的意义
— 确保C代码以统一的C方式被编译成目标文件
#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的一个重要升级
- 函数重载通过函数参数列表 区分 不同的 同名函数
- extern关键字能够实现C和C++的相互调用
- 编译方式决定符号表中的函数名的最终目标名
最后一句话是什么意思呢,就是说一个函数如果C语言编译方式得到的目标名是一种,但是这个函数的重载函数以C++编译方式编译得到的目标名是不同的,所以编译方式决定了最终的目标名。