大家好,上一期我们介绍了初步介绍了C++的入门知识,本期文章我们继续来学习剩下的知识,大家记得三连支持一下哦!
一、缺省参数
缺省参数这个词大家可能是第一次听说,那么它是什么呢?
1.缺省参数概念
我们知道在定义函数的时候通常都会有形参,而形参是实参的一份临时拷贝,在C语言中调用函数时就必须要传实参过来。而C++中引入了缺省参数,即:缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。
也就是说我们可以给定形参一个值,这样在调用函数时就不用必须传实参了。如:
2.缺省参数分类
缺省参数也有不同的类型主要分为两种:
(1)全缺省参数
全缺省参数,顾名思义,就是所有形参都缺省。
如:
全缺省参数我们在传实参的时候相传几个就传几个,没有传实参的形参,就使用缺省参数。如:
全缺省参数使用起来是比较灵活的。
(2)半缺省参数
半缺省参数的意思不是有一半的形参缺省,而是至少有一个形参缺省。
半缺省参数有一下注意事项:
1. 半缺省参数必须从右往左依次来给出,不能间隔着给;
2. 缺省参数不能在函数声明和定义中同时出现;3. 缺省值必须是常量或者全局变量;
4. C语言不支持(编译器不支持)。
什么意思呢?我们举个例子来看:
这是为什么呢?
从左往右缺省和间隔着都会产生歧义,举个例子:
还要注意一点的是:使用半缺省参数时,参数一定要传足够不然也会报错。
缺省参数不能在函数声明和定义中同时出现,我们在做项目时函数的声明和定义是分离的也就是声明和定义可能在不同的文件中,这个时候缺省参数往往放在声明中。如:
注意:如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该
用那个缺省值。
缺省参数我们现在可能感受不到它的用处,但是在后面我们会经常用到,到时大家就能感受到它的好处。
二、函数重载
我们知道在C语言中是不允许有同名的函数存在的,但是在C++中允许同名函数存在。
1.函数重载概念
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这
些同名函数的形参列表(参数个数或类型或类型顺序)不同,常用来处理实现功能类似数据类型
不同的问题。
简单来说就是C++中允许同名函数存在,但是函数的参数不能相同。下面我们就来依次介绍。
2.函数重载的条件
(1)参数类型不同
这个很好理解,就是函数的参数类型不同,我们举例来看:
(2)参数个数不同
参数个数不同函数也可以重载,如:
(3)参数类型顺序不同
上面我们介绍了参数类型和个数不同时函数可以重载。但是当参数类型和个数都相同时怎么办?
如:
这个时候我们只需要改变参数的顺序即可。如:
当然如果一个函数参数的类型都是一样的,这个时候就不能有参数类型,个数都相同的函数与之构成重载。如:
上面三个条件合在一起可以满足平常许多的情况了。
注意:
(1)重载的函数如果我们要使用浮点型传值参数类型要用double型,因为编译器默认的就是double型用float型会报错,如:
(2)同一作用域满足重载规则可以同名,不同域不需要满足重载规则也可以同名。如:
但是要是展开命名空间就不可以,如:
(3)我们知道char型和int型其实是一样的,因为字符在程序中是以ASCII码的形式存在,所以我们传值的时候给char型传int型,给int型传char型都是正确的。这就导致函数重载时出现歧义。如:
但是我们int型就传数字,char型就传字符就不会出现上面的情况。如:
3.C++支持函数重载的原理
了解到这里,小伙伴们可能会有一个疑问,为什么C++支持函数重载,而C语言不支持函数重载呢?下面我们就来简单了解一下。
首先来回答一下这个问题,函数名修饰。
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函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则。
下面我们就来看看在Linux下中C语言和C++的函数名是怎么修饰的。
C语言:
我们可以看到,在Linux下采用gcc编译完成后函数名的修饰没有发生改变。
C++:
在Linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。
通过以上对比我们就可以理解为什么C语言不支持函数重载,而C++支持。因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。
以上我们只是了解一下C++为什么支持函数重载。
三、引用
1.引用的概念
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空
间,它和它引用的变量共用同一块内存空间。我们可以理解引用是一个变量的外号。
那么引用是怎么使用的呢?
类型& 引用变量名(对象名) = 引用实体;
如:
这里我们要注意:引用的变量和它共用一块内存空间。如:
注意:引用类型必须和引用实体是同种类型的。
2.引用的特性
引用有许多的特性和需要注意的地方。下面我们依次来看:
(1)引用在定义时必须初始化
引用在定义的时候必须初始化,不能像普通变量一样,先定义出来之后再赋值。如:
(2)一个变量可以有多个引用
这个也很好理解,我们可以认为一个变量有多个外号,并且变量的外号还可以起外号,它们都共用变量的空间。如:
(3)引用一旦引用一个实体,再不能引用其他实体
引用只能有一个实体,不能再做其它变量的外号。如:
3.使用场景
上面我们学习引用的使用方法,下面我们来了解一下它的使用场景。
(1)做参数
引用可以用来做函数的参数,像我们在写交换函数时要用指针做参数,这里我们就可以用引用来代替指针。如:
这里我们可以看到引用好像有点像指针,它底层的实现确实和指针一样,但是在语法层面上和指针还是有区别的。
引用做参数在有些情景下是很方便的,如有时需要我们传二级指针时就可以用引用代替,这样就可以避免使用二级指针了。如:
(2)做返回值
引用不仅可以做参数,还可以做返回值。但是我们要注意:如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。如:
4.引用中的权限问题
我们先来看一段代码:
我们可以看到这段代码报了错,这是为什么呢?这就涉及到权限问题了。
权限的问题在指针里面也有涉及到,感兴趣的小伙伴可以自己去探索一番。
5.引用和指针的区别
上面我们提到过,在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。
我们来看下引用和指针的汇编代码对比:
我们可以看到引用和指针的汇编指令是一样的。
既然我们说在语法层面是不一样的,那么不一样在哪呢?
引用和指针的不同点:
1. 引用概念上定义一个变量的别名,指针存储一个变量地址;
2. 引用在定义时必须初始化,指针没有要求;
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体;
4. 没有NULL引用,但有NULL指针;
5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节);
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小;
7. 有多级指针,但是没有多级引用;
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理;
9. 引用比指针使用起来相对更安全。
好了,以上就是本篇文章的全部内容了,后面将继续讲解C++入门的知识,感谢大家的观阅!创作不易,三连支持一下呗!