大家都知道C语言函数命名时候相同名字是编译不过的,在编译时就会报错。
而C++是有函数重载的,相同的函数只要参数(个数,类型,顺序)不同,就可以重命名
//C
int func(int i)
{//...
}
int func()//重命名报错
{//...
}
-------------------------------------------
//C++
int func(int i)//不同参数
{
//...
}
int func()//成功
{
//...
}
这个是时候我们就会抛出疑问为什么C没有函数重载,而C++有函数重载?
原理是什么呢?
C++函数重载原理剖析
//.C
int func(int i)
{//...
}
int func()//重命名报错
{//...
}
大家知道编译中的汇编时会形成.o文件并会形成符号表符号表,C编译器在符号表中直接以函数名为标识生成重载函数,导致歧义和冲突,而且在链接时,依旧会产生歧义和冲突,因为都是直接使用函数名去查找识别的,而重载函数的符号名相同
在汇编中符号表的生成会发现函数名相同导致错误。
链接时,函数重载会导致C编译器不知道时调用那个函数,导致相同报错。
而让我们来看C++编译器是怎么做的
C++引入函数名修饰规则
C++编译器会在汇编时将函数命名为_Z1Funci ---
C++中函数名修饰的规律:_Z+函数长度+函数名+类型首字母。
汇编时在该域中只有函数声明,没有定义时,函数地址先_Z1fv(?)不会报错---v为void类型参数
在编译的过程中函数名不是直接使用,而是根据函数名修饰规则改变后成为汇编符号表中的。
在函数链接时候使用声明的函数会在链接时去往另一个.o文件中寻找定义,由于他们的名字都是函数名修饰规则改变后,导致同名函数在链接时互不影响
链接的主要工作去其他符号表中寻找声明过函数的定义!
ps:有些函数构成重载但是不可被所以比如
涉及缺省参数
void func()
{
}
void func(int a=1)
{
}
int main()
{
func(1)//成功
func()//这个时候编译器报错
return 0
}
为什么会报错?因为函数调用的时候,不传实参,func()本来就不需要参数而缺省参数也可以不传参数,这个时候编译器就不知道调用那个函数了,造成了歧义与冲突
涉及函数引用
void func(int a)
{
}
void func(int &a)
{
}
int main()
{
int b=10;
func(b);//这个时候编译器报错
return 0
}
为什么会报错?因为函数调用的时候,传的实参类形是int ,但是func(int a)与func(int &a)都是接收int类型的实参,这个时候编译器就不知道调用那个函数了,造成了歧义与冲突。