1 C++ 中的函数重载
-
函数重载(Function Overload)
- 用同一个函数名定义不同的函数
- 当函数名和不同的参数搭配时函数的含义不同
-
示例
-
Demo
#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(int argc, char *argv[]) { printf("%d ", func(3)); //3 printf("%d ", func(4, 5)); //9 printf("%d ", func("ABCD")); //4 return 0; }
-
-
函数重载至少满足下面的一个条件
- 参数个数不同
- 参数类型不同
- 参数顺序不同
2 函数默认参数与函数重载
-
当函数默认参数遇到函数重载会发生什么?
-
Demo
#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); printf("c = %d ",c); return 0; }
-
编译
test.cpp:15:21: error: call of overloaded ‘func(int, int)’ is ambiguous int c = func(1,2); ^ test.cpp:3:5: note: candidate: int func(int, int, int) int func(int a,int b,int c = 0) ^ test.cpp:8:5: note: candidate: int func(int, int) int func(int a,int b) ^
-
-
编译器调用重载函数的准则
-
将所有同名函数作为候选者
-
尝试寻找可行的候选函数
- 精确匹配实参
- 通过默认参数能够匹配实参
- 通过默认类型转换匹配实参
-
匹配失败
- 最终寻找到的候选函数不唯一,则出现二义性,编译失败
- 无法匹配所有候选者,函数未定义,编译失败
-
-
函数重载的注意事项
- 重载函数在本质上是相互独立的不同函数
- 重载函数的函数类型不同
- 函数返回值不能作为函数重载的依据,函数重载是由函数名和参数列表决定的
-
示例:函数重载的本质
-
Demo
#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 ", (int(*)(int, int))add); printf("%p ", (int(*)(int, int, int))add); return 0; }
-
编译运行
0x804840b 0x8048418
-
3 重载与指针
-
问题:下面的函数指针将保存哪个函数的地址?
- 第一个
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(1); //1
-
函数重载遇到函数指针:将重载函数名赋值给函数指针时
- 根据重载规则挑选与函数指针参数列表一致的候选者
- 严格匹配候选者的函数类型与函数指针的函数类型
-
示例:函数重载 VS 函数指针
-
Demo
#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 double(*PFUNC)(int a); //函数指针,无法匹配 int main(int argc, char *argv[]) { int c = 0; PFUNC p = func; c = p(1); printf("c = %d ", c); return 0; }
-
编译
test.cpp: In function ‘int main(int, char**)’: test.cpp:26: error: no matches converting function ‘func’ to type ‘double (*)(int)’ test.cpp:4: error: candidates are: int func(int) test.cpp:9: error: int func(int, int) test.cpp:14: error: int func(const char*)
-
-
注意
-
函数重载必然发生在同一个作用域中
-
编译器需要用参数列表或函数类型进行函数选择,不考虑返回值,但是当遇到函数指针时,需要考虑函数类型(参数,返回值),需要严格匹配
-
无法直接通过函数名得到重载函数的入口地址
-
Demo
#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 ", add); printf("%p ", add); return 0; }
-
编译
test.cpp: In function ‘int main()’: test.cpp:15: error: overloaded function with no contextual type information test.cpp:16: error: overloaded function with no contextual type information
-
修改:利用强制类型转换
#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 ", (int(*)(int, int))add); //强制类型转换为函数指针:int(*)(int, int) printf("%p ", (int(*)(int, int, int))add);//强制类型转换为函数指针:int(*)(int, int,int) return 0; }
-
-
4 C++ 和 C 相互调用
-
实际工程中 C++ 和 C 代码相互调用是不可避免的
-
C++ 编译器能够兼容 C 语言的编译方式
-
C++ 编译器会优先使用 C++ 编译的方式
-
extern
关键字能够强制让 C++ 编译器进行 C 方式的编译extern "C" { //do C-style compilation here }
-
示例:
-
Demo
//add.h int add(int a, int b); //add.c #include "add.h" int add(int a, int b) { return a + b; } //main.c #include <stdio.h> #include "add.h" int main() { int c = add(1, 2); printf("c = %d ", c); return 0; }
-
编译
/tmp/ccnrEzcf.o: In function `main': test.cpp:(.text+0x19): undefined reference to `add(int, int)' collect2: ld returned 1 exit status
-
修正
//add.h int add(int a, int b); //add.c #include "add.h" int add(int a, int b) { return a + b; } //main.c #include <stdio.h> extern "C" { #include "add.h" } int main() { int c = add(1, 2); printf("c = %d ", c); return 0; }
-
编译运行
3
-
-
问题:如何保证一段 C 代码只会被以 C 的方式被编译?
__cplusplus
是 C++ 编译器内置的标准宏定义__cplusplus
的意义:确保 C 代码以统一的 C 方式被编译成目标文件
#ifdef __cplusplus extern "C"{ #endif //C-style Compilation #ifdef __ cplusplus } #endif
-
示例:C++ 调用 C 函数
-
Demo
//main.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 ", c); //3 return 0; }
-
C 语言编译器:
gcc main.c
通过 -
C++ 编译器:
g++ main.c
通过
-
-
注意
-
C++ 编译器不能以 C 的方式编译重载函数
-
编译方式决定函数名被编译后的目标名
-
C++ 编译方式将函数名和参数列表编译成目标名
-
C 编译方式只将函数名作为目标名进行编译
-
Demo
int add(int a,int b) { return a + b; } int add(int a,int b,int c) { return a + b + c; }
-
C++ 方式编译:
g++ -c test.cpp -o test.oo
->nm test.oo
00000000 T _Z3addii 0000000e T _Z3addiii U __gxx_personality_v0
-
C 方式编译
extern "C" { int add(int a,int b) { return a + b; } int add(int a,int b,int c) { return a + b + c; } }
-
编译:
g++ -c test.cpp -o test.oo
test.cpp: In function ‘int add(int, int, int)’: test.cpp:8: error: declaration of C function ‘int add(int, int, int)’ conflicts with test.cpp:3: error: previous declaration ‘int add(int, int)’ here
-
-
-