IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> [C++] 深入理解C++函数重载底层原理 C++入门(2) -> 正文阅读

[C++知识库][C++] 深入理解C++函数重载底层原理 C++入门(2)

本篇文章我们要深入理解函数重载。还不了解函数重载的小伙伴可以看看上篇文章末尾简单理解一下[C++] helloworld 解析 C++入门(一)

本篇主要解决的问题:

1.C语言不支持重载,C++支持重载,为什么?

2.C++如何支持重载?

目录

问题的引入

1.函数重载(C++)

1.1编译链接过程

1.1.1预处理?

1.1.2编译

1.1.3汇编

1.1.4链接

2.C语言 对函数重命名

3.总结

问题的引入

首先我们复习一下函数重载。函数重载就像是一词多义,一个函数名可以有多个意思。函数可以根据参数的不同选择进入不同参数的函数。

那么,这种情况属于函数重载吗?

short Add(short left, short right)
{
}
int Add(short left, short right)
{
}

答:这种是不构成函数重载的,这是因为函数重载跟返回值没有关系,在VS2019下编译器也会主动报错。

那么今天我们就是来底层深挖,为什么和返回值没有关系,又为什么和参数的顺序,个数,类型有关系呢??

1.函数重载(C++)

在我们学习C语言的过程中我们知道编译链接的过程,为了更好的展示这个过程,我们使用Linux来看这段过程。

1.1编译链接过程

首先我们复习一下编译连接的过程:

1、预处理 -- 头文件展开,宏替换,条件编译,去掉注释
?f.i ?test.i
2、编译 -- 检查语法,生成汇编代码
?f.s ?test.s
3、汇编 -- 把汇编代码转换成二进制的机器码
?f.o? test.o
4、链接 -- 找调用函数的地址,链接对应上,合并到一起 合并符号表
?a.out

?

1.1.1预处理?

在预处理的过程中,会进行头文件的展开,宏替换,条件编译,去掉注释等一些操作,这个过程非常的重要。在这里我们重点说说头文件展开。

头文件展开:

假设现在我们创建一个f.h的头文件,f.cpp的文件。

?那么头文件的展开就是将f.cpp的头文件进行展开。如下图所示:

此时的cpp文件为:

?

经过预处理的过程,我们在编译的过程中我们就可以找到函数了。?

1.1.2编译

检查语法,生成汇编代码,汇编代码是一种指令级的语言,如果有语法错误,就会在这个阶段出现。

我们在VS下看看什么是指令级的代码,这些指令级的代码是给CPU准备的,CPU是执行指令的。

例如:我们看看最简单的helloworld的指令代码

1.1.3汇编

当语法没问题的时候,我们就来到了汇编,此时这个指令级代码CPU不认识,机器都只认识0和1。因此汇编的过程就是将汇编代码转换成二进制的机器码。

1.1.4链接

找调用函数的地址,链接对应上合并到一起,合并符号表。

我们来理解一下这个过程:

这预处理过程中头文件展开如下

在编译的过程中还会生成一个符号表,主要记录函数定义和函数地址的映射,那符号表为什么要生成函数地址的映射呢。此时我们来看

?在main函数的指令中,有两句指令call,call后面所跟的就是函数的地址,函数的名字和函数的地址。然后我们来看一下这个过程,真正的函数地址就是第一句指令的地址。函数的名字也会有自己的命名规则。

?

为了更好的看函数的命名规则,我们在linux下看看这个细节。当函数名相同,参数不同时,他们的函数名会有一套新的命名规则。在不同的话函数调用中,他们参数类型首字符带进命名规则中去了。

新的函数名:_Z 函数名长度 函数名 类型首字母

因此即使函数名相同,但参数的类型不同,顺序不同,个数不同都会产生不同新的函数名。

因此再调用的时候对应的名字是不相同的。因此所对应的地址也是不同的?

?

这也是为什么C++支持函数重载的原因。

2.C语言中处理

那我们在C语言中再看看这个过程,他的新的函数名是怎么命名的,我们首先创建3个文件

?我们再在Linux下看看C语言是如何处理函数名的

此时我们发现C语言对函数的命名只有函数名本身,和参数无关。

我们在Linux下看看报错信息:我们创建两个f函数,我们在Linux下用gcc编译看报错信息,我们发现这时就会报错说函数命名发生冲突。

因此我们知道C语言对函数的命名只有函数名本身,因此如果在C语言中,函数名相同时,就会报错,因此C语言是不支持函数重载的。

3.总结

1.C++支持函数重载是因为C++在符号表中存储的函数的定义和函数的地址。C++中对函数的命名规则有了新的变化:_Z 函数名长度 函数名 类型首字母 。

因此参数的类型,个数,顺序不同就会不同的命名。名字不同地址不同。这也是为什么C++支持函数重载的原因。

2.我们发现在新的命名规则中是不包括返回值类型的,因此返回值类型不同并不会对函数的命名产生影响,这也是返回值不构成函数重载的原因。

short Add(short left, short right)
{
}
int Add(short left, short right)
{
}

3.C语言中在生成符号表中存储的只是原函数的名字,那么如果函数的名字相同时就会产生命名冲突。这就是为什么C语言不支持函数重载的原因。

(本篇完)

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-02 13:24:33  更:2022-05-02 13:24:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:21:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码