函数重载的概念:
函数重载是C++语言的一个重要特性
在同一作用域,多个函数在函数名相同的情况下,形参列表不同的就构成重载
例如:
int &add(int a, int b)
{
static int c = a + b;
return c;
}
double &add(double a, double b)
{
static double c = a + b;
return c;
}
为什么需要函数重载
主要是命名冲突问题, (虽然using可以解决命名冲突,但这里不描述)
如果没有函数重载
以上述的add函数为例, 我们在做整型与整型之间的加法运算时, 起了个名字叫add, 做浮点型加法时,取名为了和add区别就要起个别的名字,比如… double_add?那整型加法不如改名叫int_add更好…
从语义上讲,无论数据类型是什么都是做加法,就连我们在做数学题时也不会刻意强调类型, 因此单一的add表示所有类型的加法才是比较自然也符合人的习惯的,而且名字多了不好用也不好记,非常反人类!
有了函数重载,就不用因为参数的原因为同一功能的函数命名而纠结了,同时也不建议把不同功能的函数都起一样的名字,明明是除法却要叫add也很反人类
C++支持函数重载的原因
要明白为什么C++支持函数重载需要先提出几个问题:
1.C语言为什么不支持函数重载?
2.为什么重载函数要满足形参列表不同?
(以下内容使用Linux来举例, Windows下是相同的规则,不同的表示形式,不做举例)
问题1:C语言为什么不支持函数重载?
在Linux系统下,创建一个.c文件
int add(int a, int b)
{
return = a + b;
}
int main()
{
return 0;
}
编译连接生成可执行文件,然后使用objdump -S查看汇编代码
解答问题:
可以看到刚才的函数名add出现在了汇编代码中,C语言区别函数只依赖函数名,因此如果有相同函数名的函数, 那么汇编中会出现两个相同的名字,这样在C语言编译连接时就无法区分该使用哪个函数
问题2:为什么重载函数要满足形参列表不同?
在Linux系统下, 将刚才的.c文件改为.cpp文件, 编译连接生成可执行文件,然后使用objdump -S查看汇编代码
int add(int a, int b)
{
return = a + b;
}
可以看到add->_Z3addii,可以明显的看出C++汇编生成的函数名是与C语言不一样的
一个函数包含返回值,函数名,形参列表
以最初的add函数为基准逐个修改对比来找找规律
只修改add函数的返回值,其余不变:
double add(int a, int b)
{
return = a + b;
}
只修改函数名其余不变:
int addtion(int a, int b)
{
return = a + b;
}
只修改形参列表,其余不变:
int add(double a, double b)
{
return = a + b;
}
为了方便观察,将上述内容制成表格:
样例 | 返回值 | 函数名 | 形参列表 | 反汇编中的名字 |
---|---|---|---|---|
1 | int | add | int, int | _Z3addii |
2 | double | add | int, int | _Z3addii |
3 | int | addtion | int, int | _Z7addtionii |
4 | int | add | double, double | _Z3adddd |
观察发现如下规律:(事实就是这样,本次实验样例少,可以自己尝试更多的例子)
- 返回值不同,并不能区分两个同名函数, 所以仅有返回值不同不能构成重载
- 函数名不同引起的改变除了名字从add->addtion以外, 还有_Z3->_Z7,变化的只有名字因此改变的数字与名字有关,add是3个字符,而addtion是7个字符,所以可以推测数字是名字的长度
- 形参列表改变后,_Z3add之后的ii->dd, 由于只改变了形参列表,所以变化与形参列表有关, int的首字母就是i,double的首字母就是d,所以可以推测,最后的字母是形参列表中数据类型的首字母
解答问题:
C++区别函数依赖于函数名和形参列表
同名的情况只有样例1,2,4观察他们在反汇编中的名字可以看到,返回值不同不能区分同名函数,而形参列表不同可以区分同名函数,这就是为什么重载函数的形参列表必须不同