函数重载你真的了解吗?

news2024/10/5 22:23:57

1.什么叫函数重载?

函数重载(Function Overloading)是指在同一个作用域内,允许定义多个具有相同名称但参数列表不同的函数。具体而言,函数重载允许你定义同名的函数,但这些函数应该有不同的参数类型、参数个数或者参数顺序。

举例

上述代码中有两个名为Print的函数,虽然名字一样,但是参数类型不一样。在c语言中会认为这两个是一个函数,后一个定义的会覆盖前面一个。在c++中函数重载的概念引入之后便认为这两个函数是不同的两个函数,并会根据传参类型自动选择相应的函数,由此一来我们的代码会变得更加灵活和易读

2.参数不同构成函数重载

值得注意的是,如果仅仅是函数返回值不同是无法构成函数重载的。在函数调用时,编译器会根据实际传递的参数类型来确定调用哪个函数,而不是仅仅依赖于返回值类型。

3.函数重载的原理

为什么c语言不支持函数重载而c++支持呢?

在c/c++中,一个程序要想运行起来需要经历以下几个阶段:预处理、编译、汇编、链接。

预处理会将.c/.cpp文件中的代码经过头文件展开、去除注释、宏替换、条件编译转换成 .i文件

编译会将 .i 文件中的代码翻译成汇编代码,生成 .s文件

汇编会将 .s中的汇编代码翻译成二进制指令,生成 .o文件(也叫目标文件)

链接会将程序所有的 .o 文件进行链接生成 .exe后缀的可执行文件

各个阶段具体是怎么实现的可以去看

c语言的程序环境和预处理(一眼丁真)_c语言环境打击那-CSDN博客

其中,在链接这个阶段会进行合并段表、符号表的合并和符号表的重定位等行为。简单来说,链接操作通过合并这些符号表等实现了程序中各个文件的连接,也就是能在一个文件中通过符号表找到另一个文件定义的函数地址并执行这个函数。 

1.实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们
可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标
文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。那么
怎么办呢?
2. 所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就
会到b.o的符号表中找Add的地址,然后链接到一起。(老师要带同学们回顾一下)
3. 那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则

4.函数名修饰规则

函数名修饰(Name Mangling)通常是指编译器对函数名进行的一些变换或修改,以便区分同名函数或支持函数的重载。在C语言中,函数名修饰是相对较简单的,因为C语言本身不支持函数的重载。

4.1对比c/c++处理函数名

C语言中的函数名不会被修饰: 在C语言中,函数名不会被编译器修改或添加任何前缀或后缀,因为C语言本身不支持函数的重载。因此,C语言的函数名在源代码中的写法和编译后的二进制代码中是一样的。

C++语言中的函数名修饰: C++支持函数的重载,因此编译器需要在编译阶段对函数名进行修饰,生成唯一的函数名以区分不同的函数。修饰的方式通常包括添加函数参数类型参数个数等信息。

4.2c++具体是怎么修饰函数名的呢?

以linux举例,在Linux中,g++ 编译器使用 C++ ABI (Application Binary Interface) 标准,其函数名修饰规则是按照 Itanium C++ ABI 来进行的。以下是一些基本规则:

  1. 函数名修饰格式: C++ 编译器根据函数的参数类型、参数个数、以及一些其他信息生成一个唯一的函数名。这个过程称为 name mangling。修饰后的函数名通常包含原函数名以及一些用于标识参数类型和个数的信息。

  2. 名称修饰的参数类型表示: 常见的参数类型表示包括基本数据类型、指针、引用等。例如,int 类型可能用 i 表示,double 类型可能用 d 表示。

  3. 参数个数和其他信息: 修饰还包括参数的个数和其他一些信息,以区分函数重载和模板特化等情况。

观察以下函数

void myFunction(int x, double y);//修饰后的函数名为:_Z10myFunctionid

g++编译器对该函数名修饰后变成了_Z10myFunctionid,在这个例子中,_Z10 是由编译器添加的前缀(不同编译器可能不一样),myFunction 是原函数名,后面的 id 表示参数的类型,i 表示 int 类型,d 表示 double 类型。

4.3用汇编代码查看函数名是否被修饰 

观察以下代码

以上代码是在linux中的vim编译器运行的,具体的操作指令大家无需了解。我们只需要知道gcc是编译c语言的编译器,而g++是编译c++代码的编译器。我们现在用两种方式去编译同一份代码,并观察其 汇编阶段生成的 .s 文件,这样我们就能在汇编层面观察到函数名被修饰的样子。

用gcc编译

用g++编译 

我们可以看到,add函数名被修饰成了_Z3addii 其中后缀"ii" 指的是两个参数的类型。这样一来,两个函数的名字名即使相同,我们也能因为其参数不同生成两个不同的“函数名”。

5.总结

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

同时需要注意的是,函数名修饰的具体的修饰规则可能会因编译器版本、编译选项、操作系统等因素而有所不同。在实际的应用中,除非涉及到与其他语言或库的交互,否则大多数情况下不需要深入了解或处理函数名修饰。

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

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

相关文章

代码随想录算法训练营Day44|完全背包理论基础、518.零钱兑换II、377. 组合总和 Ⅳ

目录 完全背包理论基础 完全背包问题 算法实现 518.零钱兑换II 前言 思路 377. 组合总和 Ⅳ 前言 思路 算法实现 总结 完全背包理论基础 题目链接 文章链接 完全背包问题 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是…

计网——应用层

应用层 应用层协议原理 网络应用的体系结构 客户-服务器(C/S)体系结构 对等体(P2P)体系结构 C/S和P2P体系结构的混合体 客户-服务器(C/S)体系结构 服务器 服务器是一台一直运行的主机,需…

springboot 整合 PowerJob实现定时任务调度

最近项目需要使用定时任务,而使用了PowerJob做任务调度模块,感觉这个框架真香,今天我们就来深入了解一下新一代的定时任务框架——PowerJob! 简介 PowerJob是基于java开发的企业级的分布式任务调度平台,与xxl-job一样…

关于破解IDEA后启动闪退的问题

问题描述:2023.1启动不了,双击桌面图标,没有响应。 解决办法: 打开C:\Users\c\AppData\Roaming\JetBrains\IntelliJIdea2023.1\idea64.exe.vmoptions 这个文件。 内容如下所示: 删除红框的数据以后,再登录…

ARM架构可视化ROS消息方案部署

ARM架构可视化ROS消息方案部署 三种方案, 1. webviz 2. foxglove 3. rosviz 注: web要用firefox, chromimum用不了, 可能是因为取消了时间同步机制的原因 先说三种方案的优劣, webviz 延迟比较高, 但是部署相对简单, foxglove 部署比较费劲, 但是效果不错, 延迟低, 本文会尽…

MySQL篇----第二篇

系列文章目录 文章目录 系列文章目录前言一、MyIASM二、Memory三、数据库引擎有哪些前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、MyIASM MyIASM是 MySQL默…

Dash :一个超漂亮的 python Web库!

你好,Dash 是一个非常方便的 Python 库,它可以非常非常帮助你构建基于 Web 的应用程序,而且最棒的是你无需使用 JavaScript! 不仅如此,Dash 还是一个专门用于创建分析 Web 应用程序的用户界面库。 如果你是一个使用 …

【Algorithms 4】算法(第4版)学习笔记 03 - 1.3 背包、队列和栈

文章目录 前言参考目录学习笔记0:预热1:栈1.1:栈的链表实现1.1.1 代码实现1.2:栈的数组实现1.2.1:定容栈1.2.2:可调整大小数组1.2.3:代码实现1.3:链表与数组的取舍2:队列…

Vue中的常用指令

一、常用指令 概念:指令(Directives)是 Vue 提供的带有 v- 前缀 的 特殊 标签属性。 为啥要学:提高程序员操作 DOM 的效率。 vue 中的指令按照不同的用途可以分为如下 6 大类: 内容渲染指令(v-html、v-t…

电脑风扇控制温度软件 Macs Fan Control Pro 中文

Macs Fan Control Pro是一款专为Mac用户设计的风扇控制软件,旨在提供更精细的风扇转速控制和温度监控。这款软件通过实时监测Mac内部硬件的温度,自动或手动调整风扇的转速,以确保系统温度保持在理想范围内。 Macs Fan Control Pro提供了直观…

使用gcc/g++查看C语言预处理,编译,汇编,连接,以及动静态库的区分

文章目录 使用gcc/ggcc如何完成编译后生成可执行文件?预处理(进行宏替换)编译(生成汇编)汇编(生成机器可识别代码)连接(生成可执行文件或库文件)最后记忆小技巧 在这里涉及到一个重要的概念&…

【Tomcat与网络2】一文理解Servlet是怎么工作的

在前面,我们研究了如何用idea来启动一个Servlet程序,今天我们就再来看一下Servlet是如何工作的。 目录 1.Servlet 介绍 2.Servlet 容器工作过程 3.Servlet的扩展 不管是电脑还是手机浏览器,发给服务端的就是一个 HTTP 格式的请求&#xf…

双非本科准备秋招(14.1)—— 力扣刷题

今天做两个有点难度的题。 1、295. 数据流的中位数 手写堆实现: 加入元素: 如何维护一个中位数?我们考虑一下堆的特点,大顶堆堆顶是一个最大值,小顶堆堆顶是一个最小值,那么,如果我们可以把数…

R语言学习case7:ggplot基础画图(核密度图)

step1: 导入ggplot2库文件 library(ggplot2)step2&#xff1a;带入自带的iris数据集 iris <- datasets::irisstep3&#xff1a;查看数据信息 dim(iris)维度为 [150,5] head(iris)查看数据前6行的信息 step4&#xff1a;画图展示 plot2 <- ggplot(iris,aes(Sepal.W…

踩坑STM32CubeMX生成Makefile工程无法使用printf(“%f“)

过去一年偶有接触STM32开发时都是使用STM32CubeMX生成Makefile的工程&#xff0c;具体开发环境见配置Clion用于STM32开发&#xff08;Makefile&#xff09;&#xff0c;但没想到今天在使用printf打印输出浮点数时无法正常输出&#xff0c;不仅printf无法使用&#xff0c;其他涉…

024 增强for循环

什么是增强for循环 用法 int[] arr {1,3,5,7,9}; for (int i : arr) {System.out.println(i); } 拓展 增强for不止用于数组&#xff0c;还可以用于集合。 增强for是for的偷懒写法&#xff0c;必定可以被for的写法的代替&#xff0c;但for不一定会被增强for代替。

【详细教程】Kubernetes集群部署:使用kubeadm创建集群

文章目录 一、虚拟机准备&#xff08;一&#xff09;主机基本配置&#xff08;二&#xff09;安装docker&#xff08;三&#xff09;配置cri-docker环境&#xff08;四&#xff09;安装kubeadm、kubelet、kubectl&#xff08;五&#xff09;克隆主机 二、环境配置工作&#xff…

扫盲软件开发工具低代码

目录 一、低代码是什么&#xff1f; 二、低代码平台的优势和劣势都是什么&#xff1f; 三、低代码操作方式 四、写在最后 一、低代码是什么&#xff1f; 低代码是一套可视化开发工具&#xff0c;它帮开发者把前后端基础功能写扎实&#xff0c;开发者只需要通过填表配置或拖…

Java SWT Composite 绘画

Java SWT Composite 绘画 1 Java SWT2 Java 图形框架 AWT、Swing、SWT、JavaFX2.1 Java AWT (Abstract Window Toolkit)2.2 Java Swing2.3 Java SWT (Standard Widget Toolkit)2.4 Java JavaFX 3 比较和总结 1 Java SWT Java SWT&#xff08;Standard Widget Toolkit&#xff…

3593 蓝桥杯 查找最大元素 简单

3593 蓝桥杯 查找最大元素 简单 // C风格解法1&#xff0c;通过率100%&#xff0c;多组数据处理样式//str "abcdefgfedcba" //abcdefg(max)fedcba//str "xxxxx" //x(max)x(max)x(max)x(max)x(max)#include<bits/stdc.h>const int N 1e2 10;char …