C++函数重载详解

举报
YIN_尹 发表于 2023/08/16 16:01:22 2023/08/16
【摘要】 函数重载自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。5.1 函数重载概念在C++中呢引入了函数重载,这个也是C语言所没有的,那什么是函数重载呢?函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数的个数 或 参数的类型 或 参数类型的顺序)不同,常用来处理实现功能类似但数据类型不同的问题...

函数重载

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。

5.1 函数重载概念

在C++中呢引入了函数重载,这个也是C语言所没有的,那什么是函数重载呢?

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数的个数 或 参数的类型 或 参数类型的顺序)不同,常用来处理实现功能类似但数据类型不同的问题。

  1. 参数类型不同

首先来看函数重载的第一种情况:参数类型不同。即函数名和参数个数都是一样的,只是参数类型不同。

int Add(int left, int right)
{
    cout << "int Add(int left, int right)" << endl;
    return left + right;
}
double Add(double left, double right)
{
    cout << "double Add(double left, double right)" << endl;
    return left + right;
}

像这样两个函数,它们的函数名完全相同,唯一的区别就是参数类型和返回类型不同

🆗,那大家都知道这样的情况在C语言中肯定是会报错的

f2607371a7654f61b9b8a2f2d554319d.png

那C语言中我们想解决这个错误就只能改动一下,让这两个函数的名字不再相同。

但是C++引入了函数重载就支持这种情况的出现了:

5fdc7bf7c76e4c8bba58627535747d8d.png

cbf4d87ab5dc4c0fb0a5c32474866676.png

这样看起来我们是调用的同一个函数,但是程序会自动根据我们传的参数类型进行匹配,如何匹配我们后面也会介绍到。

在有些时候还是很方便的。

  1. 参数个数不同

第二种情况:函数名和返回类型都相同,但是参数的个数不同。

// 2、参数个数不同
void f()
{
    cout << "f()" << endl;
}
void f(int a)
{
    cout << "f(int a)" << endl;
}

bd4198ed0ea54ce38413204d8300d474.png

  1. 参数类型顺序不同

第三种:参数类型的顺序不同,什么意思呢,比如下面这种情况:

void f(int a, char b)
{
    cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
    cout << "f(char b, int a)" << endl;
}

参数的类型都是int和char,但是顺序不一样。

25f4208dfc33445497a4f2d82d69580e.png

5.2 C++支持函数重载的原理–名字修饰

首先大家思考一个问题:


我们上面提到C++中出现函数重载情况的时候,我们去调用时程序会根据我们传的参数类型去匹配对应的函数。


那大家想一下,相比C语言的函数调用过程,这个匹配的过程会不会导致程序变慢,或者说让运行时间变长呢?


🆗,是不会的哦。

因为这个匹配的过程其实是在编译期间就完成的,所以不会对运行时间造成影响。

我们之前专门有一篇文章讲解C/C++程序一步步变成可执行程序的过程,大家忘了的话可以回顾一下链接: link


那我们继续,那在编译期间,编译器是如何对这些重载函数进行区分和匹配呢?


🆗,那原因呢就在于C++做了一件事情,就是对函数名进行了名字修饰。

而C语言是不会进行这样的处理的,因为C语言不允许函数重载,即C程序中不会出现同名函数的,所以C语言可以直接通过函数名去匹配对应的函数,一旦出现同名函数,那这时就发生冲突了,就报错了。


那具体C++是怎么对函数名进行修饰的?


那其实每个编译器都有自己的函数名修饰规则,这取决于编译器的实现者。

由于Windows下vs的修饰规则过于复杂:

可以给大家看一下在vs上C的函数名和C++修饰之后的函数名的对比:

c14042c1738d4b10b912290203a19381.png

c61fcf9d898b45d89744e74df609d5bb.png

相比于Windows下vs的修饰规则,Linux下g++的修饰规则简单易懂,下面我们可以看看g++对函数修饰后的名字:

  1. 采用C语言编译器编译后结果(gcc)
  2. 31f97b22ba0e419ca3def6d803ef6dcf.png
  3. 结论:在linux下,采用gcc编译完成后,函数名字没有发生改变。
  4. 采用C++编译器编译后结果(g++)
  5. 00a0e2c411a34b308e68bfb314a9c0d5.png
  6. 结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。

我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】

Windows下名字修饰规则

b812f8f3d7324e62b1d07b5beb81b003.png

对比Linux会发现,windows下vs编译器对函数名字修饰规则相对复杂难懂,但道理都是类似的,我们就不做细致的研究了。

通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。


最后大家再思考一个问题:如果两个函数只有函数返回值类型不同,能否构成重载?

c7bdbd4cb54f49129217fd7e14e47e9e.png

是不行的。

为什么不行?

90f93c57124e4b0c94ce1cd3223d2435.png

因为我们在调用的时候,是不是不能分辨出返回类型是啥啊,这样是不合理的。

所以:

如果两个函数函数名和参数是一样的,只有返回值不同是不能构成重载的,因为调用时编译器没办法区分。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。