1,重载与指针:编程
1,下面的函数指针将保存哪一个函数的地址? ide
1 int func(int x) 2 { 3 return x; 4 } 5 6 int func(int a, int b) 7 { 8 return a + b; 9 } 10 11 int func(const char* s) 12 { 13 return strlen(s); 14 } 15 16 typedef int(*PFUNC)(int a); 17 int c = 0; 18 PFUNC p = func; 19 c = p(1); // which function to call ?
2,重载函数的函数名不表明函数的入口地址,要加入相应的函数类型方可;函数
2,函数重载赶上函数指针:测试
1,将重载函数名赋值给函数指针时:spa
1,根据重载规则挑选与函数指针参数列表一致的候选者;指针
2,严格匹配候选者的函数类型与函数指针的函数类型;code
1,比重载更加严格,也要加上返回值类型的匹配;blog
2,不进行任何形式的默认类型转换;作用域
3,函数重载 VS 函数指针编程实验:编译器
1,main.cpp 文件:
1 #include <stdio.h> 2 #include <string.h> 3 4 int func(int x) 5 { 6 return x; 7 } 8 9 int func(int a, int b) 10 { 11 return a + b; 12 } 13 14 int func(const char* s) 15 { 16 return strlen(s); 17 } 18 19 typedef int(*PFUNC)(int a); //typedef double (*PFUNC)(int a) 时错误; 20 21 int main(int argc, char *argv[]) 22 { 23 int c = 0; 24 25 PFUNC p = func; 26 27 c = p(1); 28 29 printf("c = %d\n", c); 30 31 return 0; 32 }
2,输出结果:
1
4,注意:
1,函数重载必然发生在同一个做用域中;
1,C++ 中不止一个做用域,还有类做用域等;
2,C 只有一个全局做用域;
2,编译器须要用参数列表或函数类型进行函数选择;
1,重载时,若是不碰到指针,则用参数列表选择,若是碰到指针,则用函数类型来选择;
3,没法直接经过函数名获得重载函数的入口地址;
1,强制类型转换为函数指针能够;
5,C++ 和 C 相互调用:
1,实际工程中 C++ 和 C 代码相互调用是不可避免的;
1,项目中决定采用 C++ 的时候,也极可能会调用旧的用 C 代码编写的代码,这时就涉及到 C++ 调用 C 代码;
2,C++ 编译器编译 C 的源码能够直接经过,可是工程中有一些 C 代码被编译成目标文件,至关于在 C++ 中会用到用 C 语言编写和编译的第三 方的库,这些第三方库仍是要收费的,既然收费了,就要合理的利用;
3,见以下示例:
1,add.h 文件:
1 int add(int a, int b);
2,add.c 文件:
1 #include "add.h" //不能用 #include <add.h>,不然找不到 add.h 文件,这里不用包含这个文件以及定义 1 中的 add.h 头文件也能够编译经过,可是后续的使用这个函数就只能包含源码,因此仍是要调用头文件; 2 3 int add(int a, int b) 4 { 5 return a + b; 6 }
3,用 gcc -c add.c -o add.o 编译生成 add.o 文件;
4,在 main.c 文件中调用:
1 #include <stdio.h> 2 #include "add.h" 3 4 int main() 5 { 6 int c = add(1, 2); 7 8 printf("c = %d\n", c); 9 10 return 0; 11 }
5,经过 g++ main.cpp add.o(第三方库不提供源代码,只提供头文件和编译生成的目标文件) 命令编译器显示:undefin dreference to 'add(int, int)';
6,经过符号表命令 nm 查阅 nm add.o 获得: 00000000 T add,说明符号表中已经有 add 函数了;
7,由于用 C++ 编译器调用 C 编译器编译的代码,不能成功;
2,C++ 编译器可以兼容 C 语言的编译方式;
1,C++ 天生须要兼容 C;
2,C++ 和 C 编译方式是不一样的,C++ 编译器可以兼容 C 语言编译方式, 可是有优先级问题;
3,C++ 编译器会优先使用 C++ 编译的方式;
4,extern 关键字能强制让 C++ 编译器进行 C 方式的编译;
1,代码示例:
1 extern "C" // 告诉编译器大括号中的代码以 C 方式编译; 2 { 3 // do C-style compilation here,能够有不一样的多个函数; 4 }
2,更改 main.cpp 文件以下:
1 #include <stdio.h> 2 3 extern "C" 4 { 5 #include "add.h" 6 } 7 8 int main() 9 { 10 int c = add(1, 2); 11 12 printf("c = %d\n", c); 13 14 return 0; 15 }
6,C++ 调用 C 函数编程实验:
1,见本博客 5.4.2内容;
7,问题:
1,如何保证一段 C 代码只会以 C 的方式被编译?
1,不能直接调用 extern "C",由于这是 C++ 中才有的,C 语言中不支持这样的写法,此处是一段 C 代码无论在 C 编译器仍是 C++ 编译器都只以 C 方式编译,因此就要在 C 代码中来入手;
2,若是在 C 编译器中编译带有 extern "C" 的代码,则会报错,在 C++中不会,报错的内容为“expected identifier(标识符) or '(' before string constant”;
8,解决方案:
1,_cplusplus 是 C++ 编译器内置的标准宏定义;
1,测试当前的编译器是否为 C++ 编译器,由于在 C 编译器内部不含有这个宏;
2,_cplusplus 的意义:
1,确保 C 代码以统一的 C 方式被编译成目标文件;
2,#ifdef _cplusplus // 判断是否为 C++ 编译器;
1 #ifdef _cplusplus // 判断是否为 C++ 编译器; 2 extern "C" { // 保存这一行代码; 3 #endif 4 5 // C-style Compilation here 6 7 #ifdef _cplusplus // 判断是否为 C++ 编译器; 8 } // 保存这一行代码; 9 #endif
9,注意事项:
1,C++ 编译器不能以 C 的方式编译重载函数;
1,编译方式可以决定函数名被编译后的目标名是什么;
2,编译方式决定函数名被编译后的目标名:
1,C++ 编译方式将函数名和参数列表编译成目标名;
2,C 编译方式只将函数名做为目标名进行编译;
10,小结:
1,函数重载是 C++ 对 C 的一个重要升级;
2,函数重载经过函数参数列表区分不一样的同名函数;
3,extern 关键字可以实现 C 和 C++ 的相互调用;
1,extern "C" 代码块中不能出现重载函数;
4,编译方式决定符号表中的函数名的最终目标名;