函数重载:
在相同作用域中的多个函数,具有相同的名字而形参表不同
不能仅仅基于不同的返回类型而实现函数重载。返回值是不影响函数签名的。
C++函数重载底层实现原理是C++利用name mangling(倾轧)技术,来改名函数名,区分参数不同的同名函数。
编译器通过函数名和其参数类型识别重载函数。为了保证类型安全的连接(type-safe linkage),编译器用参数个数和参数类型对每一个函数标识符进行专门编码,这个过程有时称为“名字改编”(name mangling)或“名字修饰”(name decoration)。类型安全的连接使得程序能够调用合适的重载函数并保证了参数传递的一致性。编译器能够检测到并报告连接错误。
1、查看符号表
(1)nm目标文件
(2)objdump -t 目标文件
(3)readelf -s 目标文件
(4)strings 目标文件
1.1 gcc编译
(1)tesst.c
int func(int a){
};
(2)编译
gcc -c test.c -o test.o
(3)查看符号
objdump -t test.o
1.2 g++编译
(1)test.cpp
int func(int a){
};
int func(int a,int b){
};
(2)编译
g++ -c test.cpp -o test.o
(3)查看符号
objdump -t test.o
_Z是规定前缀,4是函数名的字符个数,i是参数列表类型i的首字母
注意:不同系统和编译器的命名倾轧方式是有所不同的。
2、命名反倾扎
2.1 名字改编转化成函数名
使用c++filt命令可以很容易把名字改编转换成函数名。
c++filt _Z4funci
2.2 查看反倾轧的符号表
nm -C 目标文件
3、禁用命名倾轧
C++命名倾轧的函数是无法被C语言调用的。C++的函数必须是没有倾轧的才能调用。
使用声明extern "C"的函数会禁止命名倾轧,这样C++的函数就可以被C语言调用。
例如:
(1)sum.h
#ifndef __CPP_H_
#define __CPP_H_
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
int sum(int* arr,int n);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // __CPP_H_
通常为了头文件可以同时被C++/C使用,通常把extern "C"放在__cplusplus条件宏定义中。
(2)sum.cpp
#include "cppFunc.h"
#include <numeric>
using namespace std;
int sum(int* arr,int n){
return accumulate(arr,arr+n,0);
}
(3)sum_test.c
#include <stdio.h>
#include "cppFunc.h"
int main(){
int arr[] = {
1,2,3,4,5};
printf("%d\n",sum(arr,5));
}
4、原理小结
4、综合练习
(1)Test.h
#pragma once
//C++的时候,显示extern "C"
//C的时候,不显示extern "C"
#ifdef __cplusplus
extern "C"{
//在函数声明中使用
#endif
int Add(int a,int b);
void FuncTest();
#ifdef __cplusplus
}
#endif
(2)Test.cpp
#include "Test.h"
int Add(int a,int b){
return a+b;
}
void FuncTest(){
}
(3)overload.cpp
#include "Test.h"
int Add(float a,long b){
return a+b;
}
class Simple{
public:
Simple(){
}
Simple(const Simple&){
}
Simple& operator=(const Simple&){
return *this;}
~Simple(){
}
};
void Func(){
}
int main(){
int c = Add(10,11);
// Simple s;
// Simple s2(s);
// s2=s;
}
文章评论