C++——深入探究函数重载

news2025/2/26 9:33:05

文章目录

  • 概述
  • 函数重载
  • 函数重载的概念
    • 函数重载的细节
  • C++支持函数重载的原理——名字修饰(name Mangling)

概述

本篇博客讲诉的是c++函数重载是什么,以及了解其种的一些特征以及重载函数的意义,并且运用linux中的g++编译器简单探究一下函数重载底层是如何实现的。

函数重载

首先,我们先从自然语言的角度来认识一下函数重载,在地然语言中,一个词可以有多重含义,简称一词多义,人们可以通过上下文来判断该词的具体含义,一词多义正是函数重载的关键内涵。

函数重载的概念

函数重载:是函数的一种特殊情况,c++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数,类型或者类型顺序)不同,常用来处理实现功能相近数据类型不同的问题,可以说这一方面是c++对c语言的重要改进之一。

我们通过几个例子来初步了解一下函数重载:

#include<iostream>
using namespace std;

//1.参数类型不同
int add(int a, int b)
{
	cout << "add(int a, int b)" << endl;
	return a + b;
}
double add(double a, double b)
{
	cout << "add(double a, double b)" << endl;
	return a + b;
}

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

//3.参数类型顺序不同
//(其实实际意思就是参数类型不同)
void f(int a, char b)
{
	cout << "f(int,char)" << endl;

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

int main()
{
	add(10, 10);
	add(1.1, 9.8);

	func();
	func(29);

	f(10, 'a');
	f('a', 10);

	return 0;
}

从上面这串代码就可以很容易的看到函数重载的强大功能了把!但是,关于函数重载,还有一些需要注意的点。

函数重载的细节

  1. 看下面一段代码:
void func(int a, char b)
{
	using namespace std;
	cout<<"func(int a,char b)"<<endl;
}
void func(int b, char a)
{
	using namespace std;
	cout<<"func(int b, char a)"<<endl;
}

上面的代码参数顺序和类型都相同,但是形参的名字不同,构成重载吗?

如果大家对编程有一定基础,都能很容易明白,这肯定不是函数重载,形参的名字如何取,只要上面提到的形参类型,顺序,数量完全相同,就肯定不构成重载!

其实还有一种方法很好理解,如果上面的函数定义构成重载,那么如果调用
func(10,'x')
编译器能知道应该调用哪个函数吗?显然是不行的!

  1. 这也是函数重载的第二个大坑
    参数列表完全相同,返回值不同的函数能构成函数重载吗?
    如下:
int f()
{
	int tmp = 10;
	return tmp;
}
double f()
{
	int tmp = 1.1;
	return tmp;
}

这两个函数能构成重载吗?显然也是不构成!为什么呢?
其实原因也很简单,假设两个函数构成重载,能够编译通过,函数调用时,指令如下:
f();
通过这个函数调用,编译器仍然不能知到函数应该调用哪个函数,所以只有返回值不同是完全不构成重载的!

C++支持函数重载的原理——名字修饰(name Mangling)

大家是不是都有一个疑惑,cpp是如何实现函数重载的呢?换个方式问,就是cpp为什么支持函数重载,而c语言不支持呢?

这里就需要我们去简单地深入探究一下底层实现了。

下面部分可能需要一点编译链接的知识,下面是一篇作者简单探究c语言从源文件到可执行程序的过程博客,对编译链接没有了解的读者可以先看看链接的博客再食用该博客效果更佳!(doge
链接:C语言程序环境剖析——探究从.c到.exe之路

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

a.h a.cpp text.cpp

  • 预处理:头文件展开/宏替换/条件编译/去掉注释……(预处理完成之后生成.i后缀文件)
    a.i test.i
  • 编译: 检查语法,生成汇编代码
    a.s test.s
  • 汇编: 汇编代码转换成机器码

注意,这里的汇编汇编语言不是同一个东西

  • 链接:将多个头文件链接生成可执行程序

windows:xxx.exe/linux:默认a.out

其中编译和链接过程中有一个在这个部分非常重要的点就是生成符号表符号表汇总,关于符号表的具体知识在上面哪篇博客中有具体的讲解,简单来说就是符号(函数名,全局变量等等)+地址


c语言中函数符号表示:
这里在centos系统下写了一个test.c文档,内容如下:

#include<stdio.h>
int func(int a, double d)
{
	printf("func(int a, double d)\n");
}

int main()
{
	func(1, 1.1);
	return 0;
}

然后用linux中的gcc编译器输入
gcc -o testc test.c生成一个编译后的目标文件。

然后使用指令
objdump -S testc查看生成的函数的代码:

在这里插入图片描述
可以发现在c语言的编译下函数符号就直接由函数名表示。

同样的方法,我们再写一个cpp的文件,内容如下:

int func(int a)
{
	printf("func(int)");
}
int func(int a, double d)
{
	printf("func(int, double)");
}
int main()
{
	func(1);
	func(1,1.1);
	return 0;
}

换用g++编译器进行编译,指令如下:
g++ -o testcpp test.cpp

注:这里-o 后面的testcpp是在指定生成目标文件的文件名

再用同样的方法查看重载后两个函数的符号表示:
在这里插入图片描述

可以看到,cpp中对函数符号做了一定修饰,可以大致看出符号中不止有函数名,例如第一个参数在func后面还加入了i,前面加上了_Z4,而第二个func后面加上了id,这里就可以大致推理,cpp在形成符号表时对函数名进行了修饰,后面的id是int和double的缩写,这也是cpp能分辨出重载函数的原因,这个过程也叫做符号修饰

注意:并不是所有编译器上的符号修饰规则都一样!

下面是windows系统下vs编辑器的符号修饰规则图:
在这里插入图片描述

可以看到,vs编辑器对符号修饰的规则制定的还是比较复杂的,没有像g++编辑器浅显易懂。


以上就是关于C++函数重载的内容了,如果博主哪里写的有问题或者有疑惑还请大家在评论区指出😁
请添加图片描述

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

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

相关文章

线性表之顺序表(增删查改)详解

&#x1f355;博客主页&#xff1a;️自信不孤单 &#x1f36c;文章专栏&#xff1a;数据结构与算法 &#x1f35a;代码仓库&#xff1a;破浪晓梦 &#x1f36d;欢迎关注&#xff1a;欢迎大家点赞收藏关注 文章目录 &#x1f349;线性表&#x1f352;顺序表1. 概念及结构2. 接口…

数据库JDBC

数据库厂商提供一个程序来完成 API 的转换&#xff0c;对原生 API 封装再提供成JDBC 的形状。 这个程序叫数据库驱动包。 JAVA程序员要想对数据库开发&#xff0c; 就要导入对应的数据库驱动包&#xff0c;才能编写代码。 数据库驱动是让JDBC认识数据库API URL 计算机里的一…

MySQL安装与新用户的创建相关

一、MySQL安装 1. 官网下载mysql的ims包 MySQL :: Download MySQL Installer (Archived Versions) 下载好&#xff0c;双击运行。 2. 根据提示进行安装 这里选择手动安装的选项&#xff1a; 然后选择你安装的MySQL版本&#xff0c;这里是5.7 勾选自定义MySQL安装位置 下一…

教育大数据总体解决方案(7)

考勤查询 创客教室 为体现学校创新教育的成果&#xff0c;丰富学校创新实践活动&#xff0c;加强创新课程普及教育&#xff0c;把机器人创新教育作为学校的教育特色来体现&#xff0c;使学生通过理论与实践相结合的方法&#xff0c;进一步学习掌握机械、电子结构、信息技术、人…

让我们谈谈你对 ThreadLocal 的理解

介绍 ThreadLocal 从 JDK1.2 开始&#xff0c;ThreadLocal 是一个被用来存储线程本地变量的类。在 ThreadLocal 中的变量在线程之间是独立的。当多个线程访问 ThreadLocal 中的变量&#xff0c;它们事实上访问的是自己当前线程在内存中的变量&#xff0c;这能确保这些变量是线…

基于鲸鱼算法的极限学习机(ELM)回归预测-附代码

基于鲸鱼算法的极限学习机(ELM)回归预测 文章目录 基于鲸鱼算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于鲸鱼算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;本文利用鲸鱼算法对极限学习机进行优化&#xff0c;并…

kettle——数据清洗(数据表——>转换——>数据表)

目录 1、表输入 ①点击“新建”选项&#xff0c;新建数据库 ②选择“获取SQL” ③选择表a ④注意&#xff1a;字段只显示了5个&#xff0c;而一共有6个字段&#xff0c;money字段需要手动添加 2、转换 ①打开java 控件&#xff0c;设置变量 3、表输出 ①连接表b ②映…

【Redis7】Redis7 复制(重点:复制原理)

【大家好&#xff0c;我是爱干饭的猿&#xff0c;本文重点介绍Redis7 复制。 后续会继续分享Redis7和其他重要知识点总结&#xff0c;如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下吧】 上一篇文章&#xff1a;《【Redis7】Redis7 事务&管道&…

Git入门指南(手把手教学)

Git入门指南 一、什么是Git二、Git的安装下载三、git的简单实践1.创建git仓库2.Windows上生成公钥以绑定GitHub仓库3.写一个Helloworld 四、帮助学习的网站 一、什么是Git Git是一种分布式版本控制系统&#xff0c;它是由Linus Torvalds为了管理Linux内核开发而开发的。与中心化…

项目第四天

解决了路变墙 墙变路的问题 void onechange(ExMessage* msg) {if (msg->message WM_LBUTTONDOWN && msg->x > 50 && msg->x < 410 && msg->y > 50 && msg->y < 410){//printf("鼠标位置&#xff1a;x&#…

Vue.js中class与style的增强绑定

目录 一、v-bind绑定class属性 &#xff08;1&#xff09;绑定class样式&#xff0c;字符串写法 &#xff08;2&#xff09;绑定class样式&#xff0c;数组写法 &#xff08;3&#xff09;绑定class样式&#xff0c;对象写法 二、v-bind绑定内联样式style &#xff08;1&…

【CSS3】CSS3 属性选择器 ( CSS3 简介 | 属性选择器 | 属性选择器权重 )

文章目录 一、CSS3 简介二、CSS3 属性选择器权重三、CSS3 属性选择器 一、CSS3 简介 CSS3 是在 CSS2 基础上进行扩展后的样式 ; 在 移动端 对 CSS3 的支持 要比 PC 端支持的更好 , 建议在移动端开发时 , 多使用 CSS3 ; PC 端老版本浏览器不支持 CSS3 , 尤其是 IE 9 及以下的版…

【Linux 裸机篇(五)】I.MX6ULL BSP工程管理下的 Makefile编写、链接脚本

目录 一、BSP 工程二、Makefile三、链接脚本 一、BSP 工程 文件夹描述bsp存放驱动文件imx6ul存放跟芯片有关的文件&#xff0c;比如 NXP 官方的 SDK库文件obj存放编译生成的.o 文件project存放 start.S 和 main.c 文件&#xff0c;也就是应用文件 二、Makefile 1 CROSS_COMPI…

ESP32设备驱动-BMA400加速度传感器驱动

BMA400加速度传感器驱动 文章目录 BMA400加速度传感器驱动1、BMA400介绍2、硬件准备3、软件准备4、驱动实现1、BMA400介绍 BMA400 是第一款真正的超低功耗加速度传感器,不会影响性能。 BMA400 具有 12 位数字分辨率、连续测量和定义的可选带宽以及超低功耗,允许对三个垂直轴…

带有时钟使能和同步清零的D触发器

每个 Slice 有 8 个 FF 。四个可以配置为 D 型触发器或电平敏感锁存器&#xff0c;另外四个只能配置为 D 型触发器&#xff0c;但是需要记得是&#xff1a;当原来的四个 FF 配置为锁存器时&#xff0c;不能使用这四个 FF 。 &#xff08;1&#xff09;FDCE 简介 带有时钟使能…

【grpc01】入门

目录 背景 单体架构 微服务架构 代码冗余问题 服务之间调用 grpc protobuf protoc protoc-gen-go 背景 单体架构 有一些致命缺点&#xff1a; 一旦某个服务宕机&#xff0c;会引起整个应用不可用&#xff0c;隔离性差只能整体应用进行伸缩&#xff0c;浪费资源&#…

【Java基础】迷宫问题的Java代码实现

迷宫问题通常是指在给定的迷宫中&#xff0c;找到从起点到终点的路径的问题。迷宫通常由障碍物和自由空间组成&#xff0c;其中障碍物是不可穿越的区域&#xff0c;自由空间可以穿越。解决迷宫问题的方法有很多种&#xff0c;本文使用递归算法来解决迷宫问题。 一、使用递归算法…

MATLAB简单图形绘制(五)

目录 实验目的 实验内容 实验目的 1&#xff09;掌握MATLAB图形绘制的基本原理和方法&#xff1b; 2&#xff09;熟悉和了解MATLAB图形绘制程序编辑的基本指令&#xff1b; 3&#xff09;掌握利用MATLAB图形编辑窗口编辑和修改图形界面&#xff0c;并添加图形的各种标注&…

人工智能技术在软件开发中的应用

人工智能技术的不断发展和成熟&#xff0c;使得它在软件开发中的应用越来越广泛。人工智能技术的应用可以帮助软件开发人员提高效率、降低成本、增强软件的功能性和可靠性。在本文中&#xff0c;我们将探讨人工智能技术在软件开发中的应用&#xff0c;并且提供一些实际案例&…

借助高性能计算的发展十大网络趋势

当今的网络支持复杂企业IT环境中的大量工作负载。而借助高性能计算(HPC)和人工智能/深度学习的应用程序&#xff0c;企业可以满足对更快计算周期、更高数据传输率和出色连接性日益增长的需求。 当今的网络支持复杂企业IT环境中的大量工作负载。而借助高性能计算(HPC)和人工智能…