重载(overload)
同一个标识符在不同的上下文有不同的意义
如汉语中“洗”和不同的字搭配后,有不同的含义,play 和不同的单词搭配后有不同的含义。
函数重载:用同一个函数名定义不同的函数,通过不同的参数搭配来判断不同的函数
编译器通过不同的参数来区分不同的功能。
#include <stdio.h>
#include <string.h>
int func(int x) { //一个int 型参数
return x;
};
int func(int a, int b) { //两个int型参数
return a + b;
}
int func(char* s) { //一个char* 参数
return strlen(s);
}
int main(int argc, char *argv[])
{
int a, b, c;
a = func(1);
b = func(2, 3);
c = func("abcdef");
printf("a = %d, b = %d, c = %d\n", a, b, c);
return 0;
}
函数重载至少满足下面的一个条件:
1.参数个数不同
2.参数类型不同
3.参数顺序不同
int func(int a, const char* s) {
return a;
}
int func(const char* s, int a) {
return strlen(s);
}
int main() {
func(1, "abcdef");//会调用哪个?第一个
func("abcdef", 1);//会调用第二个
return 0;
}
当函数默认参数遇上函数重载会发生什么?会遇上二义性。
int func(int a, int b, int c = 0) {
return a + b + c;
}
int func(int a, int b) {
return a + b;
}
int main() {
func(1, 2);//会调用哪一个?存在二义性,调用失败。
return 0;
}
规则:当要用默认函数参数时,不要使用重载。当要使用重载时,不要使用函数默认参数。
C++编译器调用重载函数的准则
1.编译器会将所有同名函数作为候选者
2.尝试寻找可行的候选函数
2.1精确匹配实参(参数个数和类型)
2.2通过默认参数能够匹配实参
2.3通过默认类型转换匹配实参
3.匹配失败
3.1最终寻找到的可行候选函数不唯一、则出现二义性,编译失败。
3.2无法匹配所有候选者,函数未定义,编译失败。
重载函数的注意事项
- 重载函数在本质上是相互独立的不同函数
- 重载函数的函数类型是不同的
- 函数返回值不能作为函数重载的依据,返回值不同不能作为重载函数。
函数重载时由函数名和参数列表决定的。
函数重载与函数指针
下面程序哪个函数将被调用:
#include <stdio.h>
#include <string.h>
int func (int a) {
return a;
}
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 argc, char *argv[])
{
PFUNC p = func;
p(1);//会调用哪个函数?
printf("p(1) = %d\n", p(1));
return 0;
}
当使用函数重载函数名对函数指针进行赋值时:
- 根据重载规则挑选与函数指参数列表一致的候选者
- 严格匹配候选者的函数类型与函数指针的函数类型
依据上述规则,*typedef int(*PFUNC)(int a);*会去匹配第一个函数。
c++和c的相互调用
在项目中,融合c++和c代码是实际工程中不可避免的,虽然c++编译器能够兼容c语言的编译方式,但是c++编译器会优先使用c++的方式进行编译。利用extern关键字,可以强制让c++编译器对代码以c方式进行编译。
范例:C++调用C函数
范例:C调用C++函数
统一的解决方案
__cplusplus 是c++编译器内置的标准宏定义,可以让c代码既可以通过c编译器的编译,也可以在c++编译器中意c方式编译
#ifdef __cplusplus
extern "C" {
#endif
//函数声明
#ifdef __cpulsplus
}
#endif
注意,C++编译器不能以C的方式编译多个重载函数。C语言不允许重名函数,C语言没有重载函数概念。
下面代码会编译报错,报函数重名。
#ifdef __cplusplus
extern "C" {
#endif
void f() {
}
void f(int x) {
}
#ifdef __cplusplus
}
#endif
小结
- 函数重载时C++相对于C语言的一个重要升级。
- 函数重载通过函数参数列表区分不同的同名函数。
- 函数的返回值类型不是函数重载的依据,即同名同参的函数,返回值不同,不是函数重载,会编译报错。
- extern关键字能够实现C和C++相互调用。 C和C++并不对立,可以同时存在于项目中。