【C/C++】深入理解--函数重载(什么是函数重载?为什么要有函数重载?)

news2024/11/15 18:25:10

目录

一、前言

二、 函数重载

🍎什么是函数重载

🍐函数重载的条件

 🍇函数重载的注意点

🍉为什么要有函数重载

 🍓为何C语言不支持函数重载,反倒C++可以?

💦 Linux环境下演示函数重载

 💦结论

四、总结与提炼 

 五、共勉


一、前言

        自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!” 

       同时---我们在平时写代码中也会用到几个函数但是他们的实现功能相同,但是有些细节却不同。例如:交换两个数的值其中包括(int, float,char,double)这些个类型。在C语言中我们是利用不同的函数名来加以区分。

void Swap1(int* a, int* b);            ---- int 类型
void Swap2(float* a, float* b);        ---- float 类型
void Swap3(char* a, char* b);          ---- char 类型
void Swap4(double* a, double* b);      ---- double 类型

       我们可以看出这样的代码不美观而且给程序猿也带来了很多的不便。于是在C++中人们提出了用一个函数名定义多个函数,也就是所谓的函数重载。

二、 函数重载

🍎什么是函数重载

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

        简单来说,C++允许同一作用域中出现函数名相同,参数不同,功能相似的函数,而这些函数就构成函数重载。

void Swap(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
 
void Swap(double* a, double* b)
{
	double temp = *a;
	*a = *b;
	*b = temp;
}
//这两个函数就构成函数重载

这两个函数就构成函数重载

注意: 

对于函数重载这个概念,我们在学习C语言的时候是没有听过的,因为在C语言中是不存在函数重载概念的。只有在.cpp的文件中,我们才可以进行函数重载

🍐函数重载的条件

第一要满足:函数名相同

第二要满足:参数不同,具体表现在参数类型的顺序、参数的个数、参数的类型

参数的类型不同的函数重载

参数的个数不同的函数重载


参数类型的顺序不同
 

 🍇函数重载的注意点

仅仅修改函数返回类型-------- 不能称为函数重载


因为无法区分你要调用的是谁

🍉为什么要有函数重载

        C语言不支持同一作用域存在同名函数,那么我们修改一下函数名不就行了吗?函数重载真正能体现价值的地方到底在哪呢? 
 

第一:书写函数名方便。

        比如,我们要写两个交换函数,第一个是交换两个整形,第二个是交换两个浮点型,那么你只需要都取Swap即可,不需要写成Swapi、Swapd,如果参数复杂呢?你又要写成什么呢?

       到不如直接写成Swap,然后传不同的参数,编译器会自动匹配最符合的函数。
 

第二:类中构造函数的实现也依靠函数重载

        构造函数是同名的成员函数,它一般被划分为:有参构造、无参构造、拷贝构造,它们构成函数重载。
 

第三:模板的底层实现也依靠函数重载

        模板的其实就是让编译器就为你创建重载函数,比如Swap(const T& a,const T&b)

当你传两个整形给a和b时,编译器会自动生成Swap(int* a,int* b),当你传两个浮点型double时,编译器会自动生成Swap(double* a,double* b)。


以上等等C++中好用的机制都依靠于函数重载,函数重载在C++中的地位不言而喻。

 🍓为何C语言不支持函数重载,反倒C++可以?

      有了函数重载,确实要比不支持函数重载的C语言上方便了许多,这难免会有人提问到:

  1. 既然函数重载这么好,为何C语言就不行呢?
  2. C++又是如何支持函数重载的呢?

      接下来,我就展开来讨论下:首先,为了更好的显现出其具体操作过程,我将在Linux的环境下向大家展示其具体过程。其次,解释其原理需要借助我们之前讲解过的程序编译链接,所以下文我也会带着再简要讲解下。所以,正文开始:

💦 Linux环境下演示函数重载

  • gcc编译 -- C语言版本

      首先,我们在Linux环境下创建3个目录:fun.hfun.ctest.c。来分别进行声明、定义、实现。

      注意后缀,都是以.c命名,这说明以下操作是在C语言的情况下进行的

      对上述代码编译运行后没有错误,接下来用gcc编译对它生成 tc 可执行程序.


接下来,我们在原有文件的基础上再写一个函数来确保其是函数重载 


此时我们用gcc对它进行编译:

   

        很明显发生错误,再强调下,上述操作是在C语言的基础上完成的。这就足矣说明,C语言是不支持函数重载的,想要搞清楚原因前,就要先明白程序的编译链接,看下文:

回顾程序的编译链接 

程序的编译链接我在曾经的一篇博文中已详细讲解过,这里直接给出链接:
程序环境的编译链接

针对上述的三个目录文件:fun.h、fun.c、test.c,接下来展开讨论:

程序的编译链接分为四大过程:

  1. 预处理 -- 头文件展开、宏替换、条件编译、去掉注释。预处理后生成fun.itest.i文件
  2. 编译 -- 检查语法,生成汇编代码。编译后生成fun.stest.s文件
  3. 汇编 -- 把汇编代码转换成二进制的机器码。汇编后生成fun.otest.o文件
  4. 链接 -- 合并段表、符号表的合并和符号表的重定位。通俗讲就是找调用函数的地址,链接对应上,合并到一起

看图:

  • 首先预处理:

                   1. 取消注释    -----  2. 宏替换    -----  3. 条件编译     -----  4. 头文件展开

  • 其次编译,会生成符号表(记录的是函数定义和函数地址的映射)以及函数调用指令


   这里生成了main函数的指令,其中有fun,因为还不知道确切的地址,只是有声明,所以先用?表示,接着进入链接,找调用函数的地址,链接对应上,并合并到一起 。随后就在编译形成的符号表里寻找与main函数指令相同的函数名,并找到其地址

采用C语言编译器编译后结果 

 首先我们采用查看可执行文件的反汇编指令-------objdump -S 可执行文件

查看结果:

gcc的函数名修饰规则 

有没有发现C语言直接以函数名命名,没有任何其它的修饰这么做也就注定造成了出现多个相同函数名的时候,在链接时call不知道链接哪个,因为函数名都是一样的,找不到其地址,这也就说明了C语言不支持函数重载,其链接过程的图示和上述图示一样:

 采用C++编译器编译后结果

我们采用如下指令编译:

查看结果:

  • 函数一:

  • 函数二:

g++的函数名修饰规则 

仔细观察C++版本的汇编指令,观察两个不同函数的函数名修饰样式:

  • 一个是<_Z3fid>:
  • 另一个是<_Z3fdi>:

有没有发现它把参数类型的首字母带进去了,那也就意味着你的参数的类型不同,个数不同,参数顺序不同都会导致函数名不同

这个时候,C++编译后生成的符号表里以及链接时函数调用指令应该是这个样子:


        这个时候,C++在链接的过程中,call找的就是其修饰后的函数名,函数名不同,自然不会出错,这就是C++支持函数重载的核心所在,而C语言的函数命名规则是根据函数名设定的,函数名相同的话,链接就会出错,找不到确切地址,自然不会支持函数重载
 

  • 再来确定下C++函数名的修饰规则:

_Z 函数名长度 函数名 类型首字母

而返回值的不同并不会影响到函数名的修饰规则,这也就是为什么前面强调的函数返回类型不同不支持函数重载

 💦结论

 C++支持函数重载而C语言不支持是因为函数在内存中的存储方式不相同,C语言是直接以函数名修饰而C++是_Z 函数名长度 函数名 类型首字母,导致C++支持重载,而C语言不支持重载。

四、总结与提炼 

最后我们来总结一下本文所学习的的内容📖 

  • 首先在文章的开始,我通过两个生活中的小案例先带读者了解了什么是函数重载的概念。然后讲述了有关函数重载的三种形式,分别是:【类型】不同、【个数】不同和【类型顺序】不同三种。对函数重载有了一个基本的认识
  • 然后我们便通过双系统深入探究了对于C++而言对函数在编译之后会进行一个函数名修饰,Linux环境下易理解一些,Windows环境下的解析过于复杂,若是有兴趣的读者可以继续深入

 以上就是本文要介绍的所有内容,感谢您的阅读🌹

 五、共勉

以下就是我对【C/C++】函数重载的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对C++类和对象的理解,请持续关注我哦!!!!!    

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1422911.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

云纱网签约百望云,联手打造数字化产业闭环

近日&#xff0c;百望云签约广东云纱数字科技有限公司&#xff0c;共建数字化发票管理系统&#xff0c;赋能产业链上下游供应商的协同交易与运营&#xff0c;助力企业实现数字化四流合一交易&#xff0c;打造数字化产业闭环。 云纱网是广东云纱数字科技有限公司依托于深厚的产业…

Halcon 几何测量

文章目录 算子Halcon 计算两点之间的距离案例Halcon 计算点到直线的距离Halcon 计算点到区域的距离Halcon 线到区域的距离Halcon 线到线的距离 算子 distance_pp 两点之间的距离算子 distance_pp( : : Row1, Column1, Row2, Column2 : Distance) Row1 点1的行坐标 Column1 点1的…

Django视图函数技巧,从入门到实战

文章目录 Django视图函数1.request对象的方法2.视图函数的常用的返回对象&#xff08;1&#xff09;response对象&#xff08;2&#xff09;JsonResponse对象&#xff08;3&#xff09;redirect() &#xff1a;给浏览器了一个30x的状态码 3.设置响应头和状态码&#xff08;1&am…

【Vue】前端项目引入阿里图标

【Vue&React】前端项目引入阿里图标 方式11、登录自己的iconfont-阿里巴巴矢量图标库&#xff0c;把需要的图标加入到自己的项目中去&#xff1b;2、加入并进入到项目中去选择Font class 并下载到本地3、得到的文件夹如下4. 把红框中的部分粘贴到自己的项目中&#xff08; …

2万块的郎酒,都是我们惯的

文 | 琥珀酒研社 作者 | 五画 当我看到郎酒拿出快2万一瓶纪念酒的时候&#xff0c;我就知道&#xff0c;这场高价酒的喧嚣和吵闹&#xff0c;又到了一个新的高度。 和别的行业有所不同&#xff0c;白酒很少谈智商税&#xff0c;再高的价格&#xff0c;总有个冠冕堂皇的理由。…

28个炫酷的纯CSS特效动画示例(含源代码)

CSS是网页的三驾马车之一&#xff0c;是对页面布局的总管家&#xff0c;2024年了&#xff0c;这里列出28个超级炫酷的纯CSS动画示例&#xff0c;让您的网站更加炫目多彩。 文章目录 1. 涌动的弹簧效果2. 超逼真的3D篮球弹跳&#xff0c;含挤压弹起模态3. 鼠标放div上&#xff0…

力扣hot100 数组中的第K个最大元素 堆 三路划分

Problem: 215. 数组中的第K个最大元素 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 参考 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn) Code class Solution {public int findKthLargest(int[] nums, int k…

【Django自学】Django入门:如何使用django开发一个web项目(非常详细)

测试机器&#xff1a;windows11 x64 python版本&#xff1a;3.11 一、安装Django 安装步骤非常简单&#xff0c;使用pip安装就行 pip install django安装完成之后&#xff0c;python的 Scripts 文件夹下&#xff0c;会多一个 django-admin.exe (管理创建django项目的工具)。…

Linux其实不难,做个四层板设计的终端设备就搞懂了!

前言 想掌握一个技能&#xff0c;还得靠实践。 作者想学习Linux&#xff0c;于是边学边做&#xff0c;成功开源出了一个——还不错的 四层板设计的 终端设备。 项目成本可压缩至100元以内&#xff0c;便于复刻与参考学习&#xff01; 01 开源项目描述 做了一个基于V3S芯片的…

02-opencv简单实例效果和基本介绍-上

机器视觉概述 机器视觉是人工智能正在快速发展的一个分支。简单说来,机器视觉就是用机器代替人眼来做测量和判断。机器视觉系统是通过机器视觉产品(即图像摄取装置,分CMOS和CCD两种)将被摄取目标转换成图像信号,传送给专用的图像处理系统,得到被摄目标的形态信息,根据像素…

聚类(Clustering)理论

一、无监督学习介绍 在这小节中&#xff0c;我将开始介绍聚类算法&#xff0c;这是我们学习的第一个非监督学习算法&#xff0c;我们将要让计算机学习无标签数据而不是此前的标签数据。那么什么是非监督学习呢&#xff1f;在学习机器学习知识的开始我曾简单地介绍过非监督学习&…

【Algorithms 4】算法(第4版)学习笔记 02 - 1.4 算法分析

文章目录 前言参考目录学习笔记1&#xff1a;科学方法2&#xff1a;观察举例&#xff1a;三数之和3&#xff1a;近似4&#xff1a;增长数量级4.1&#xff1a;二分查找 demo4.2&#xff1a;二分查找代码实现4.3&#xff1a;二分查找比较次数的证明&#xff08;比较次数最多为lgN…

贪吃蛇的简易实现

技术要点 贪吃蛇的简易实现会运用到语⾔函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API等,接下来首先简单介绍一下会运用到的东西。 Win32 API介绍 Windows 这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外, 它同时也是⼀个很⼤的服务中⼼…

嵌入式工程师day15(链表)

内存管理 一.内存管理: 1.malloc void *malloc(size_t size); 功能: 申请堆区空间 参数: size:申请堆区空间的大小 返回值: 返回获得的空间的首地址 失败返回NULL 2.free void free(void *ptr); 功能: 释放…

机器学习-3降低损失(Reducing Loss)

机器学习-3降低损失(Reducing Loss) 学习内容来自&#xff1a;谷歌ai学习 https://developers.google.cn/machine-learning/crash-course/framing/check-your-understanding?hlzh-cn 本文作为学习记录1.降低损失&#xff1a;迭代方法 迭代学习 下图展示了机器学习算法用于训…

idea Statistic使用

问题描述&#xff1a;本地idea版本为2018.3.5&#xff0c;安装Statistic插件后没有出现Statistic图标 原因如下&#xff1a;插件版本太新了&#xff0c;需要历史版本 解决办法&#xff1a; IDEA安装代码统计插件Statistic后左下角图标出不来(亲测)_idea statistic不展示-CSD…

从入门到精通 MATLAB:这些学习网站是不错的选择!

介绍&#xff1a;MATLAB是一种高级的数学计算软件&#xff0c;专门用于算法开发、数据可视化、数据分析以及数值计算。它是MathWorks公司推出的产品&#xff0c;自1984年推向市场以来&#xff0c;已经成为科学计算和工程设计领域的重要工具。以下是MATLAB的主要特点&#xff1a…

【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]

阅读导航 引言一、设计模式概念&#xff08;了解&#xff09;二、单例模式1. 饿汉模式&#xff08;1&#xff09;概念&#xff08;2&#xff09;模拟实现&#xff08;3&#xff09;优缺点&#xff08;4&#xff09;适用场景 2. 懒汉模式&#xff08;1&#xff09;概念&#xff…

【C++进阶08】哈希的应用(位图and布隆过滤器)

一、位图 1.1 位图的概念 面试题 给40亿个不重复的无符号整数&#xff0c;没排过序 给一个无符号整数&#xff0c;如何快速判断一个数是否在 这40亿个数中。【腾讯】 能想到的解决思路&#xff1a; 遍历&#xff0c;时间复杂度O(N)排序(O(NlogN)) 利用二分查找: logN放到哈…

计算机毕业设计 | SpringBoot+vue 教务管理系统(附源码)

1&#xff0c;项目背景 教育需求增长 随着社会的发展&#xff0c;对于教育质量的要求也在不断提高。传统的手工操作和纸质记录已经不能满足现代教学的需求。因此&#xff0c;一个自动化、数字化的教务管理系统成为了必然的选择。 信息化趋势 现代科技的飞速发展使得信息化成为…