C++入门二(更新)

重载

概念:在同一作用域内,函数参数列表不同 : 参数的个数 或 参数的顺序 或 参数的类型

代码演示:

在这里插入图片描述

补充

无参数和全缺省函数,不能定义为同一个函数名。如下图:

在这里插入图片描述

在这里插入图片描述
那么,为什么C语言没有函数重载呢?

这就得从编译链接的角度分析了。先来回顾一下编译和连接都干了什么。

预处理:头文件的包含/条件编译指令/宏展开等等… − > t e s t . i -> test.i >test.i
编译:检查语法,是否匹配。 − > t e s t s -> tests >tests
汇编:把汇编代码编译为机器指令。 − > t e s t . o -> test.o >test.o
链接:各自生成的 .o 文件链接在一起。

例如我们现在有这么一个工程:
在这里插入图片描述
我们都知道函数名其实就是个地址,但它的地址其实是第一条指令的地址,如下图,在这里插入图片描述
而我们 t e s t . c p p test.cpp test.cpp 中只有一个函数的声明,相当于只有那个 c a l l call call 的地址,其实是没有函数的地址的。当我们把 函数的定义干掉的时候。
在这里插入图片描述
其实文件编译是还可以编译的过的。这个声明就相当于你知道了这里会有定义一样。所以才可以编过。
举个例子:

你现在想买一套房子,距离叫首付还差5万块钱,那么这时候你去找你的好哥们打了个电话,说:哥们,最近我打算买房子,但首付还差五万块钱,你能不能借我五万块钱?
你哥们说:没逝没逝,五万块钱没有问题。
那么这个时候,你心里有了个底,直接把定金就叫了。

那么此时我们运行一下?
在这里插入图片描述
可以看到此时我们虽然有了声明,但是缺少定义。这个问题就出在了链接上,我们找不到 Add() 对应的定义。这就相当于该交首付了,你哥们却说钱没了。
在这里插入图片描述
此时我们加上,成功运行。

回到问题上:那么,为什么C语言没有函数重载呢?

对于在一个工程里面(声明和定义不在同一个文件中)

那么链接的时候,我们就要那我们的函数名去对应的文件中 . o .o .o 文件的函数表去查找

  • C语言查找的时候直接拿函数名去查找的。
  • C++拿修饰过的函数名去查找的

先来看一下vs的修饰:
在这里插入图片描述
如上图:

在C++中, ? f @ @ Y A X H D @ Z ?f@@YAXHD@Z ?f@@YAXHD@Z
这里的 H H H 代表 i n t int int D D D代表的是 c h a r char char,这也是为什么C++支持函数重组,而C语言直接拿函数名去查找,比如上图的 A d d Add Add 。至于修饰规则是由编译器决定的。

引用

概念:就是给变量取个别名,而且共用同一片空间。

int x = 0;
int& p = x // 这里的 int& p = x,就相当于给 x 取个别名。
p = 1; // 此时由于都指向都一个空间,x 也变为 1.

这里要注意: 别名必须初始化,就是你不能直接这样:

int& p;

在这里插入图片描述
此时 p 和 x 的地址是一样的。

在这里插入图片描述
如上图:在C语言中,我们需要两个指针,而C++只需要对参数引用即可,此时我们函数参数(形参)里面的 x 和 y x和y xy 就是 实参 x 和 y x和y xy

但是我们可以随便的取别名吗?
在这里插入图片描述

  • 如上图此时我们的 x 是不能修改的,而我们的p是可以修改的, 从不能修改 − > 可以修改 从不能修改->可以修改 从不能修改>可以修改 权力放大了,这是不行的。
    在这里插入图片描述
  • 如上图,此时 x 从可以修改 − > 不可以修改 x从可以修改->不可以修改 x从可以修改>不可以修改 权力缩小了,这是可以的。

小知识

  • 当我们强制类型转换或者存在隐式类型转换的时候,他转换的结果会先存入一个临时变量中,而这个临时变量具有常属性,相当于被const修饰,所以我们那引用接受的时候就要注意权限放大缩小的问题。

此时虽然有个警告但是还是可以编译过的。
在这里插入图片描述

当我们使用引用的时候却不行。
在这里插入图片描述
在这里插入图片描述
相减或相加也都会产生隐式类型转换,所以我们使用引用的时候要注意。

引用能完全代替指针吗?

这里先来看一下指针与引用的不同:

  • 指针指向一个地址,而引用则是给变量取别名
  • 有空指针,无空引用(引用必须初始化)
  • 当我们求指针类型的大小时,看得是环境(32位4字节),而引用则是对取别名的变量求类型大小
  • 有多级指针,但没有多级引用
  • 引用自加是对取别名的变量值进行自加,而指针的自加是偏移一个类型的大小

而且还记得在我们链表部分,当我们想要删除某个节点时,需要让这个节点的上一个节点的next指向,想要删除节点的下一个位置,这时候就需要改变指针的指向了,而我们的引用则不能改变指向,所以 引用不能改变指向 引用不能改变指向 引用不能改变指向 就是引用不能代替指针一个理由。

内联函数(inline)

概念: 以 inline 修饰的函数叫做内联函数,在调用的时候,直接展开,没有函数地址,避免了开辟栈帧的开销,提升了程序的运行效率。

这里我们先写一个加法函数。
在这里插入图片描述
可以看到此时我们是可看到,我们call了Add函数的地址去开辟了栈帧。
在这里插入图片描述

如上图,当我们加上Inline时,发现此时的Add并没有去 call,这说明并没有去开辟栈帧,而是直接计算了的,这就是内联函数。
同时在vs中,你并不能直接看到反汇编此时展开的结果,需要设置一下。
在这里插入图片描述
在这里插入图片描述

按上图流程设置一下,才可以看到。

那,函数我们都要使用内联函数吗?

显然不是,内联函数只适用于,代码量比较少的函数,举个例子:假设这里有一万个函数调用,而一个函数100行代码,那如果都用inline展开的话。

  • 不展开:10000+100 (代码行数)
  • 展开 :10000*100
    所以内联函数只适用于代码量比较少的情况,而且内联函数是否展开,跟你没有关系,依据编译器决定的 O.o?。

内联函数不建议定义和声明分开写

内联函数展开函数,那么当你把声明和定义分开时,我们声明的地方展开后都没有函数地址,那么也无法去别的 .o 文件中的函数表查找。

在这里插入图片描述

auto关键字

简化长类型(以后再说)
auto 可以自动推导右边的类型。同时给了 typeid 可以查看类型。

在这里插入图片描述

auto使用注意事项:

  • auto类型的变量必须初始化
  • auto不能作为函数参数的类型

基于范围的for循环

以往我们遍历数组的时候只能如下遍历:
在这里插入图片描述
有了auto之后, 在有范围的集合中: 在有范围的集合中: 在有范围的集合中:还可以这样:
在这里插入图片描述
不过这只使用正向遍历,而且如果我们的 a 是个地址,那么也不可以。

空值

由于 C++在定义NULL的时候,直接定义为了0,所以在C11新引入了 n u l l p t r nullptr nullptr专门来表示指针空值,所以在C语言中我们用NULL来表示空指针,那么在C++中就只能用 n u l l p t r nullptr nullptr来表示了。

思维导图

在这里插入图片描述

  • 17
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值