1、什么是重载函数
同一个函数名定义不同的函数,当函数名相同,不同的参数搭配时含义不同。
例如:
#include <stdio.h> #include <string.h> int func(int x) { return x; } int func(int x,int y) { return x + y; } int func(const char *s) { return strlen(s); } int main(int argc, char *argv[]) { printf("Begin... "); printf("%d " ,func(1)); printf("%d " ,func(2,3)); printf("%d " ,func("abcdefg")); printf("End... "); return 0; }
运行结果:
Begin... 1 5 7 End...
上面代码函数名相同,在C语言中是肯定会报错的因为C语言不支持重载函数。而在C++中是不会报错的。而且会根据参数 调用 对应的函数。
2、允许重载的条件是什么了?
2.1、参数类型不同
2.2、参数个数不同
2.3、参数顺序不同
三个条件满足其中一条即可满足重载。
例如:下面代码中的两个 func 就满足第 2.3条 参数顺序不同
#include <stdio.h> #include <string.h> int func(const char *s ,int a) { return a; } int func(int a,const char *s ) { return strlen(s); } int main(int argc, char *argv[]) { printf("Begin... "); printf("%d ",func("abc",2)); printf("%d ",func(2,"abc")); printf("End... "); return 0; }
运行结果:
Begin... 2 3 End...
3、编译器调用重载的准则:
3.1、将所有同名的函数作为候选
3.2、尝试寻找可行的候选参数
3.2.1、精确匹配实参
3.2.2、通过默认参数能够匹配实参
3.2.3、通过默认类型转换匹配实参
匹配失败的原因:
1、最终找出来的候选函数不唯一,出现二义性,编译失败。
例如:这里调用 printf("%d " func(1,2)); 的时候 就有两个条件可以匹配所以编译器也不知道应该调用那个函数。
#include <stdio.h> #include <string.h> int func(int a,int b) { return a + b; } int func(int a,int b,int c=10) { return a+b+c; } int main(int argc, char *argv[]) { printf("Begin... "); printf("%d " func(1,2)); printf("End... "); return 0; }
编译结果:
test.cpp:18:25: error: call of overloaded ‘func(int, int)’ is ambiguous printf("%d " ,func(1,2)); ^ test.cpp:4:5: note: candidate: int func(int, int) int func(int a,int b) ^~~~ test.cpp:9:5: note: candidate: int func(int, int, int) int func(int a,int b,int c=10) ^~~~
2、无法匹配所有候选者,函数未定义,编译失败
4、函数重载的注意事项。
4.1、重载函数在本质上是相互独立的函数
4.2、重载函数的函数类型不同
4.3、函数返回值不能作为函数重载的依据
函数重载是由函数名 和参数列表决定的。
5、重载与指针。
如下代码:
#include <stdio.h> #include <string.h> int func(int a,int b) { return a + b; } int func(int a,int b,int c=10) { return a+b+c; } int func(const char *s) { return strlen(s); } typedef int (*Pfunc) (int a,int b); int main(int argc, char *argv[]) { printf("Begin... "); Pfunc P= func; int c = 0; c = P(1,2); printf("c = %d ",c); printf("End... "); return 0; }
运行结果:
Begin... c = 3 End...
通过运行结果 可以清楚的看出, c = P(1,2); 其实就是调用到 int func(int a,int b) 这个函数。
使用 typedef int (*Pfunc) (int a,int b); 定义了一个 函数指针。
随后通过 Pfunc P= func; 对函数指针 P进行初始化。
调用 c = P(1,2);
在这个过程中 C++通过 typedef int (*Pfunc) (int a,int b); 定义的类型使得 Pfunc P= func; 这个初始化能够正确的匹配到 int func(int a,int b) 这个函数。
最终调用到 int func(int a,int b) 这个函数。
所以将重载函数名赋值给函数指针的时候
1、根据重载规则挑选与函数参数列表一致的候选者。
2、严格匹配候选者的函数类型与指针的函数类型。
上面说过 函数的 重载 与 返回值 无关,但是在通过函数指针指向重载函数的时候,C++会将返回值也作为编译器判断语法是否错误的依据。(这里就对应了上面第二点说的严格匹配候选者,包括匹配 返回值、函数名、函数参数)
注意:
1、只有在同一个作用域中函数才能重载。
2、编译器选择函数的 依据是 函数列表 与 函数参数
3、无法通过函数名直接得到重载函数的入口地址。(可以通过强制类型转换的到函数的入口地址,需要给编译器提供足够多的信息选择到对应函数)
例如:printf("%p ",(int(*)(int,int))func);