C++函数重载
重载函数的概念
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列 表(参数个数、类型、顺序)必须不同,重载函数通常用来声明一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。
【在c中,程序员往往需要分别设计出不同名的函数才能使用】
这个例子就不属于函数重载,因为它们知识函数返回类型不一样,形参列表是一样的。
名字修饰
名字修饰是一种在编译过程中,将函数、变量的名称重新改编的机制,简单来说就是编译器为了区分各个 函数,将函数通过一定算法,重新修饰为一个全局唯一的名称。
- C语言的名字修饰规则非常简单,只是在函数名字前面添加了下划线。比如,对于以下代码,在最后链接时就会出错。
- 由于C++要支持函数重载,命名空间等,使得其修饰规则比较复杂,不同的编译器在底下实现的方式可能都有差异。
问题一:C语言中为什么不能支持函数重载??
1、原因:C语言不能函数重载与函数编译后函数名有关。
2、C语言编译后的代码名称为”_函数名”
编译后函数名变化只是在原来的函数名前加了一个下划线,所以当同名的函数参数不同时,编译器无法解析到他们的不同,因为它们编译后的名称都相同——Add,所以C语言不能函数重载。
问题二:c++为什么能重载??
从编译结果可以看出,C++同名参数不同的函数编译完函数名称不同([email protected]@[email protected]和[email protected]@[email protected]),所以可以函数重载。被重新修饰后的名字中包含了:函数的名字以及参数类型。这就是为什么函数重载中几个同名函数要求其参数列表不同 的原因。只要参数列表不同,编译器在编译时通过对函数名字进行重新修饰,将参数类型包含在最终的名字中,就可保证名字在底层的全局唯一性。
问题三:C++中函数重载底层是怎么处理的??(c++底层有重命名机制)
它是系统直接完成了翻译与链接,直接生成了运行结果。
编译器内部完成了翻译部分:
1.预处理
1)头文件展开
2)宏的替换
3)去注释
4)条件编译
2.编译过程:将高级语言转为汇编语言
3.汇编过程:汇编语言转为二进制程序
4.链接部分:所引用的数据链接进来(在链接时,都是找名字进行链接的,就比如以上两个函数,在C语言中两个的名字一样,就会在链接中报错。C++中它们的名字不一样,所以就不会报错。)
底层的重命名机制将Add函数根据参数的个数,参数的类型,返回值的类型都做了重新命名。那么借助函数重载,一个函数就有多种命名机制。在C++调用约定(_cdecl 调用约定)中Add函数在底层被解析为:
"double cdecl Add(double,double)" ([email protected]@[email protected])
"int __cdecl Add(int,int)" ([email protected]@[email protected])
编译的时候为什么只有声明没有定义不会报错?
因为编译时只会在当前工程去找定义,如果没有找到定义找到函数声明就不找了,因为编译器认为这个函数的定义有可能在其他文件里面,先把编译时没有函数定义这个问题放过去,等到链接的时候再在其它文件查找,找不到在报错。
所以我们找出验证的方法是,写函数只给函数声明,不给函数定义,然后调用,链接是会出现错误
问题四:C++中能否将一个函数按照C的风格来编译
可以的。在函数前加extern "C",意思是告诉编译器,将该函数按照C语言规则来编译。如下图: