|
一、C++中的函数重载: 1、函数重载的概念:
代码示例演示: #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:5: error: 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:5: error: 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:22: error: call of overloaded ‘func(int, int)’ is ambiguous int c = func(1, 2); ^ test5.cpp:16:22: note: candidates are: test5.cpp:3:5: note: int func(int, int, int) int func(int a, int b, int c = 0) ^ test5.cpp:8:5: note: int func(int, int) 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.out0x40052d 0x400541 从输出结果我们可以看出这两个函数的入口地址不一样,这表明这两个函数是不同的函数。 6、小结:
二、重载函数进阶学习 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相互调用:
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.h root@txp-virtual-machine:/home/txp/add# gcc -c add.c -o add.o root@txp-virtual-machine:/home/txp/add# ls add.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.o 0000000000000000 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.out c=5 3、如何保证一段c代码只会以c的方式被编译? 解决方法如下:
extern "C" { #endif #ifdef __cplusplus } #endif 这里把main.cpp改成: #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; } 输出结果: root@txp-virtual-machine:/home/txp/add# g++ main.cpp add.oroot@txp-virtual-machine:/home/txp/add# ./a.out c = 3 4、注意事项
{ 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.oo 0000000000000000 T _Z3addii 0000000000000014 T _Z3addiii 说明ii表示两个参数,iii表示三个参数
{ 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(int, int, int)’: main.cpp:8:29: error: declaration of C function ‘int add(int, int, int)’ conflicts with int add(int a, int b , int c) ^ main.cpp:3:5: error: previous declaration ‘int add(int, int)’ here int add(int a, int b) 目标名起冲突所以报错。 5、小结:
四、总结: 好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。 |
微信公众号
手机版