1. 什么是函数重载?
我们在写作、说话的时候,根据上下文的不同,同一个词可以代表不同的含义,这样的一词多义,我们叫它重载。c++中,在同一作用域里,如果有多个功能相似的同名函数,这些函数的参数列表(参数的个数、类型、顺序)必须不同,返回值类型可以不同,这样的函数我们叫做重载函数。
例如:要实现一个加法运算,可以通过函数重载实现。
int Add(int a,int b)
{
return a+b;
}
double Add(double a,double b)
{
return a+b;
}
int main()
{
Add(1,2);
Add(1.1,2.2);
return 0;
}
这样我们只需调用Add函数,编译器会根据传递的不同参数的类型自行调用,完成加法运算。这样做不管是写代码还是读代码,都减少了我们的工作量。
2. 编译器是怎样解决命名冲突的?
首先,生成一个map文件,是程序符号、源文件、代码行信息的文本表示。在vs2008中打开项目->属性配置->连接器->调试,设置生成映像文件
可以看到经过编译,原来的Add函数已经被重新命名
原来的Add函数名被改为?Add@@YAHHH@Z 和 ?Add@@YANNN@Z,当然也就不存在命名冲突的问题了。
在c++中,编译器无法识别c规则下的函数命名,这是因为c语言编译器是将函数转化为下划线加原来的函数名,如Add在编译后将变成_Add。
而c++编译器在命名时增加了参数信息,以?Add@@YAHHH@Z为例,?代表着函数的开始,Add为原函数名,@@YA代表参数的开始,H代表返回值int,HH代表两个参数int,@Z代表结束。
如果要在c++中使用c代码,可以再前面加extern”c”,告诉编译器这是c的命名规则。
3. 重载函数的调用匹配
- 精确匹配:参数匹配不做转换,如Add(1,2)调用Add(int,int)
- 提升匹配:即整型提升,如Add(1.1,2.2)调用Add(int,int),1.1和2.2提升为整型
- 使用标准转换匹配:如int 到double、double到int、double到long double
- 使用用户自定义匹配
使用省略号匹配:类似printf中省略号参数
如果调用参数模棱两可,编译器将会报错,如Add(1,2.2)
4. 编译器是如何调用重载函数的?
分如下步骤:
1. 匹配函数名
2. 获得参数类型,选取可用函数,如没有报错
3. 匹配最佳函数,当模棱两可时报错
5. 重载函数的作用域
重载函数调用的是同一作用域的函数,如果没在同一作用域,就不能算是重载函数。内层函数会隐藏外层的同名函数。
如:
int Add(int a,int b);
double Add(double a,double b);
void test()
{
int Add(int a,int b);
Add(1.1,2.2);//这里将调用Add(int,int)
}