c++进阶2:重载原理分析

(***)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);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值