函数重载即为允许在同一作用域内,一组函数可以拥有相同函数名,不同的参数(参数个数,大小),这组函数就叫做重载函数。
注意:重载函数必须在同一作用域内,不在则不算。
两个重载函数:
1、函数名相同;
2、参数列表不同,从参数类型和个数上体现;
3、返回值可同可不同;
重载函数的作用?
1、重载函数通常被用来命名一组功能相同的函数,从而实现用同一个函数操作不同的参数。与C相比,大大提升了效率。
例如下面这个例子,我们定义两个add函数分别操作int与float。
#include<iostream>
using namespace std;
int add(int x,int y)
{
return x+y;
}
float add(float x,float y)
{
return x+y;
}
int main()
{
int a = 1;
int b = 2;
float c = 1.2;
float d = 2.1;
cout<<add(a,b)<<endl;//调用add(int,int)
cout<<add(c,d)<<endl;//调用add(float,float)
system("pause");
return 0;
}
2、 类的构造函数跟类名相同,也就是说:构造函数都同名。如果没有函数重载机制,要想实例化不同的对象,那是相当的麻烦!
3、操作符重载,丰富了已有操作符的含义。
函数重载是如何实现的?
当一组函数函数名相同时,编译器如何去决定调用哪个函数呢?这里就涉及到了一个如何解决命名冲突的问题。
我们可以做一个实验,写一组重载函数,分别在Linux和Windows下运行并查看它们的反汇编,看一下重载函数是如何重命名的。
代码选用(重载函数的作用1中的例子)
Linux下:
执行命令 objdump -d a.out >test.txt 反汇编,并将结果重定向到test.txt中。 查看test.txt文件。
打开test.txt文件后:
我们发现 int add(int,int)被重定义为----------------> (_Z3addii);
float add(float,float)被重定义为----------->(_Z3addff);
通过这次实验我们可以发现,编译之后,重载函数的名字不在相同,这样就不存在命名冲突的问题了。那么编译器是如何进行函数重命名呢?
int add(int,int)被重定义为----------------> (_Z3addii);
float add(float,float)被重定义为----------->(_Z3addff);
我们先看新名字的后半部分,猜想add代表函数名,ii代表两个int参数,ff代表两个float参数,所以,不难猜出,后半部分是 函数名+参数类型缩写。
那么Z3代表什么呢?是否与函数返回值有关,但是,上面两个函数返回值一个为int,一个为float,两个为什么会相同呢?
我们再写几个函数做一下验证:
void print(int i)---------------->_Z5printi;
void print(char c)------------->_Z5printc;
char *print(char* c)---------->_Z5printPc;
从上我们可以看出Z+数字 与返回值有一定关系。但具体的与返回值的关系我们不再深究,这与编译器有关,在Windows下会得到不同的结果。但是命名规则相同 “返回值类型+函数名+参数”
同理Windows下:
相同的代码
int add(int ,int)---------------------->?add@@YAHHH@Z;
float add(int ,int)------------------->?add@@YAMMM@Z;
具体我们不再深究,道理都是相同的,这里我把在Windows下查看的方法告诉大家(我用的是VS2010)。
在Debug目录下找到 ".map" 文件打开即可。
编译器是如何调用匹配重载函数的呢?
这里有几个规则:
1、精确匹配:参数匹配而不做转换,或者只是做微不足道的转换,如数组名到指针、函数名到指向函数的指针、T到const T;
2、提升匹配:即整数提升(如bool 到 int、char到int、short 到int),float到double;
3、使用标准转换匹配:如int 到double、double到int、double到long double、Derived*到Base*、T*到void*、int到unsigned int;
4、使用用户自定义匹配;
5、使用省略号匹配:类似printf中省略号参数
一般情况下,我们多用到精确匹配与提升匹配,看下面的例子。
#include<iostream>
using namespace std;
void print(int x)
{
cout<<x<<endl;
}
void print(double x)
{
cout<<x<<endl;
}
void print(char x)
{
cout<<x<<endl;
}
void print(char *x)
{
cout<<x<<endl;
}
int main()
{
int a = 1;
short b = 2;
float c = 1.1;
char d = 'a';
char *str ="abc";
print(a);//精确匹配,调用print(int)
print(b);//提升匹配,调用print(int)
print(c);//提升匹配,调用print(double)
print(d);//精确匹配,调用print(char)
print(str);// 精确匹配,调用print(char*)
system("pause");
return 0;
}
但是,当在定义相同功能重载函数时,函数不能过多也不能过少。不然会出现不必要的麻烦。
例如:
定义了两个函数
void print(char x);
void print(long x);
int main()
{
int i = 1;
print(i);//调用print(char )?,还是print(long)?
}
此时就会出现问题!!!!
关于编译器是如何选择重载函数,恕我才疏学浅,并没有深究,这里给大家一个链接,大牛实力讲解C++函数重载,希望能对大家有所帮助。
http://www.cnblogs.com/skynet/archive/2010/09/05/1818636.html