文章目录
(***)1. 基本原理知识
函数重载:在相同作用域中的多个函数,具有相同的名字而形参表不同。
不能仅仅基于不同的返回类型而实现函数重载。返回值是不影响函数签名的。
C++函数重载底层实现原理是C++利用name mangling(倾轧)技术,来改名函数名,区分参数不同的同名函数。
编译器通过函数名和其参数类型识别重载函数。为了保证类型安全的连接(type-safe linkage),编译器用参数个数和参数类型对每一个函数标识符进行专门编码,这个过程有时称为“名字改编”(name mangling)或“名字修饰”(name decoration)。类型安全的连接使得程序能够调用合适的重载函数并保证了参数传递的一致性。编译器能够检测到并报告连接错误。
objdump -t
查看符号表
_Z开头的文件;(重载文件)
(***)2. gcc
编译
不能压榨,所以不能进行重载;
test.c
int func(int a){
};
- 编译
gcc -c test.c -o test.o
- 查看符号
objdump -t test.o
函数名 | 名字改编 |
---|---|
int func(int a); |
func |
(***)3. g++
编译
test.cpp
int func(int a){
};
int func(int a,int b){
};
- 编译
g++ -c test.cpp -o test.o
- 查看符号
objdump -t test.o
函数名 | 名字改编 |
---|---|
int func(int a); |
_Z4funci |
int func(int a,int b); |
_Z4funcii |
_Z
是规定前缀,4
是函数名的字符个数,i
是参数列表类型i
的首字母
注意:不同系统和编译器的命名倾轧方式是有所不同的。
(***)4. 命名反倾轧
名字改编转化成函数名
使用c++filt
命令可以很容易把名字改编转换成函数名。
例如:
c++filt _Z4funci
(***)5. 实例
(1)编写代码(001_test.c)
#include <stdio.h>
void Func(int,int){
}
void Func(int){
}
void Func(){
}
class Simple{
int n;
public:
Simple(int n):n(n){
}
Simple(const Simple&){
}
Simple& operator=(const Simple&){
return *this;
}
~Simple(){
}
void Func(){
}
};
int main(){
Simple s(10);
Simple s1 = s;
s1 = s;
// printf("Func=%p\n",&Func);
printf("main=%p\n",&main);
}
(2)编写代码
- 编译
gcc -c test.c -o test.o
- 查看符号
objdump -t test.o
反编译
c++filt _Z4funci
(***) 6. 禁用命名倾轧
C++命名倾轧的函数是无法被C语言调用的。C++的函数必须是没有倾轧的才能调用。
使用声明extern "C"
的函数会禁止命名倾轧,这样C++的函数就可以被C语言调用。
编译出来的函数名仅仅保留名字,与gcc编译的结果一样;
(1)这样的函数不支持重载;
extern "C" int func(int a){
return a*10;
}
#if(0)
int func(){
return 0;
}
#endif
(完整代码见002_stop.cpp)
#include <iostream>
using namespace std;
extern "C" int func(int a){
return a*10;
}
/*使用声明`extern "C"`的函数会禁止命名倾轧,这样C++的函数就可以被C语言调用。
编译出来的函数名仅仅保留名字,与gcc编译的结果一样;
(1)这样的函数不支持重载;*/
#if(0)
int func(){
return 0;
}
#endif
int main()
{
int n = func(20);
return 0;
}
(***) 7. c/c++的交叉编译
(***) 7. 1 c++环境编译c文件
情况一:直接编译c文件
g++ xxx.c //直接编译c文件
情况二:c++里面使用c语言的语法
(1)添加需要的头文件;
(2)添加需要的函数,功能相同的话,选择c++里面的函数,避免矛盾;
(***) 7. 2 c环境编译c++文件
步骤一:头文件(array.h)需要注意:
(1)头文件里面包含cpp文件里面的函数声明,
(2)但是不能包含extern “C”,不识别;
int sum(int* arr, int n);
void reverse(int* arr, int n);
int max_element(int* arr,int n);
步骤二:(array.cpp)需要注意:
(1)使用extern “C”实现函数的实现;
//(1)使用extern “C”实现函数的实现;
extern "C" int sum(int* arr, int n){
return accumulate(arr,arr+n,0);
}
(