C++函数重载的本质

函数重载定义

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表中的参数个数类型顺序必须不同,常用来处理实现功能类似数据类型不同的问题。

函数重载条件

a.参数类型不同

void Print(int a, int b)
{
	cout << " Print(int a, int b) " << endl;
}

void Print(double a, double b)
{
	cout << " Print(double a, double b) " << endl;
}

b. 参数个数不同

void Print(int a, int b)
{
	cout << " Print(int a, int b) " << endl;
}

void Print(int a, int b, int c)
{
	cout << " Print(int a, int b, int c) " << endl;
}

c. 参数顺序不同

void Print(int a, int* b)
{
	cout << " Print(int a, int* b) " << endl;
}

void Print(int* a, int b)
{
	cout << " Print(int* a, int b) " << endl;
}

函数重原理

为了方便展示函数重载的原理,我们在Linux环境下编写3个文件:头文件func.h源文件func.c和test.c文件
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

我们回顾一下一个程序的编译过程:

  • 预处理-> 头文件展开、宏替换、条件编译、去注释,生成.i文件
  • 编译-> 语法分析、词法分析、语义分析等,生成.s文件
  • 汇编-> 形成符号表、汇编代码转换成二进制机器码,生成.o文件
  • 链接-> 合并段表、符号表合并和符号表重定位

在链接过程中,链接器看到test.o调用f()函数,但是没有f()函数的地址,就会到func.o的符号表里找f()函数的地址,然后链接到一起。那么编译器会使用哪个名字去func.o里去找f()函数地址呢,

  1. 我们通过反汇编查看C编译器的函数名修饰
    在这里插入图片描述

在这里插入图片描述

我们分别对f()函数以及f(10)函数进行调用,可以看到C语言编译器完成编译后,函数名字的修饰没有发生改变。
总结:C语言不支持函数重载,因为在编译的时候,两个重载函数的函数名相同,在func.c符号表中存在歧义和冲突,其次,链接的时候也存在歧义和冲突,因为他们都是直接使用函数名去标识和查找,而重载函数的函数名相同,故C语言不支持函数重载

下图是C语言编译器对函数重载的报错:
在这里插入图片描述

  1. 我们还是调用f()函数和f(10)函数,再来看一下C++编译器对函数名的修饰规则
    在这里插入图片描述

总结:
1. 可以清楚的看到,在Linux下,采用g++编译完成后,函数的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。
2. 有了函数名的修饰规则,只要参数不同,func.o符号表里面重载的函数就不存在二义性和冲突了。
3. 链接的时候,tset.o的main函数里面去调用两个重载的函数,查询地址时,也是明确的,链接时使用修修饰后的函数名进行查找。
【函数名修饰规则:Z+函数长度+函数名+类型首字母】,不同编译器有不同的函数名修饰规则

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值