一.缺省函数
运用场景:
例:在通讯录项目时,可以省去初始化函数,通过参数的变化可以选择实现初始化/增删查改。
图示:
(图中的StackInit函数就是缺省函数,当我们传入栈的地址时且没有传入第二个参数时,它会默认传入另一个参数4)
注意事项:
只有参数的后部参数才是可以缺省,即缺省函数参数后不可以再跟正常参数
缺省函数的定义和声明:
缺省函数只能放在函数声明中——编译器必须在使用函数之前知道缺省值
二.命名空间域
引入:在实际运用代码的过程中,可能存在局部变量之间命名冲突/库与局部变量命名之间相互冲突的情况,因而我们可以在局部域全局域之外设置一个区域:命名空间域。要使用时通过 a)展开命名空间域 / b)指定访问命名空间域 来实现。
程序在编译时的优先顺序:局部域->全局域->展开的命名空间域
三.函数重载
【函数重载】
是函数的一种特殊情况,C++允许在同一作用域中声名几个功能类似的同名函数显著特征:这些同名函数的形参列表(个数,类型,类型顺序)不同
注意点:对 返回值 没有要求 ,注意声明!(例:缺省函数)
图示:(注意函数声明时,是否存在缺省函数等问题)
四.引用
1.含义与特点
引用,即取别名。它的最大特点是编译器不会为引用变量而开辟空间,他们共用同一块空间。
2.引用和指针的区别(主要)
1.引用使用时必须要初始化。
2.引用在初始化时引用一个实体后,不能再次引用其他实体,只能赋值。
3.引用使用起来更安全。
图示:
3.引用的实际使用
作为输出型参数时,面对大对象/深拷贝对象时,由于不用另外开辟空间拷贝,可以提高效率
1.适用场景
2.修改返回值+获取返回值 (使通讯录代码更简洁)
1.不适用场景:
适用场景:(静态区栈帧不销毁)
2.实际应用
- 在通讯录中,用传统的方法,需要“查找"到对应pos位置后再“修改”
- 而运用“引用作为返回值”,可直接对查找到的值进行修改。
原本操作:
改进后操作:
3.引用过程中的权限问题(平移,缩小,放大)
首先我们要知道,临时变量是具有常性,const 修饰的类型也具有常性,static的数据存储在静态区同样具备常性。
const和static的权限理论上平级,而临时变量的权限低于二者。
只能存在权限平级和权限缩小的情况,不能存在权限放大的情况。通俗而言:权限低的不能给权限(常性)强的取别名。
权限相关知识点:【权限等级较高的是const和具有常属性的量,权限较低的是普通数据】
权限高的或平级的可以给另一量取别名/取地址(权限的缩小和平移)
权限低的不能给另一量取别名/取地址(权限的放大)
图示:
1.平级和权限缩小的情况
2.权限平移情况
3.权限放大情况
PS:const原则上不能修改,但是可以通过找到其空间直接修改。(指针/别名)
五.C++中的NULL与空指针区别
- 在C++中,NULL表示“ 0 ”,实际是一个宏。
- 在C++中要表示 空指针,使用 nullptr。
- 图示:
六. 内联函数
1.内敛函数适用“短小,使用频繁的函数”
当实现加法功能时,需要频繁调用加法函数,调用函数的过程中包含着频繁地开辟栈帧空间和关闭空间,会让程序运行速度变低。而解决类似问题可以使用“宏函数”,但是宏函数面临——易出错(需要括号确保直接替换后不受影响)。在这时使用内联函数,不会频繁开辟空间,大大提高了程序的运行速度。顶中顶有没有!!但别急,它也还有缺点呢~
2.内敛函数的缺陷/特点
内联函数的本质是通过牺牲空间换时间,运用内联函数程序的运行速度大大提升,但于此同时程序的大小也会急剧增大。因此面对一些逻辑稍微复杂的运算(循环/递归)便会大大造成冗余。
inline对于编译器也仅仅是一个建议,最终是否成为inline,编译器自己会判断。
且默认debug状态下,inline不会起作用。
3.内联函数声明和定义必须要放在一起的原因
编译器一旦把某个函数作为内联函数处理,就会在其调用的位置展开,即该函数没有地址,源文件编译后不会形成符号表,没有链接冲突。同时也不能在其他源文件中调用,故一般都是直接在源文件中定义内联函数——可以在同一个项目不同的源文件中定义函数名相同但实现不同的inline函数。
七.类
1.C++兼容C,C语言中的结构体strcut也算是一种类,是public(公有)的,可以被类外直接访问。
2.类中的函数默认是内联函数,具体是否是内联函数编译器会判断。如果将其定义和声名分开,即类放在.h文件,定义函数放在.cpp文件,函数不为内联函数。
1.类的组成与计算类的大小(含结构体内存对齐规则)
类由访问限定符划分,类中既有成员变量,又有成员函数
计算类的大小,只用考虑成员变量的大小
例如:上图中,类的大小为8字节
PS:内存对齐,本质上是牺牲空间换取效率。通过调整默认对齐数可以对这一过程进行动态调整。
2. 空类的大小
没有成员变量的类对象,需要1byte,是为了占位,表示对象存在
3. This指针
This指针本质是形参,所以this指针是和普通参数一样存在函数调用的栈帧里
1.编译器对This指针的处理本质——不允许修改this,但是允许修改this指向的值
void Print(Date* const this) { cout << this->_year << "-" << this->_month << "-" << this->_day << endl; }
2.This不能在形参和实参显示传递,但是可以在函数内部显示使用
void Print() { // this不能在形参和实参显示传递,但是可以在函数内部显示使用 //this = nullptr; cout << this << endl; cout << this->_year << "-" << _month << "-" << _day << endl; }
3.例题对比:传入空指针时,this的运作状况
重点注意:p->Print()并非解引用操作
注意点:Print的地址不在对象中
4.const成员/成员函数
将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this 指针,表明在该成员函数中不能对类的任何成员进行修改
图示:
一.用const修饰this指针的好处——含权限知识点
PS:权限知识点在下方
用const修饰this指针的好处:普通对象和const对象都能调用
图示:
权限相关知识点:【权限等级较高的是const和具有常属性的量,权限较低的是普通数据】
- 权限高的或平级的可以给另一量取别名/取地址(权限的缩小和平移)
- 权限低的不能给另一量取别名/取地址(权限的放大)
图示:
二.能否所有的成员函数都加上const?
答案:不是的,要修改成员变量的函数不能加。
三.几个的使用场景
请思考下面的几个问题:
1. const对象可以调用非const成员函数吗?no
2. 非const对象可以调用const成员函数吗?yes
3. const成员函数内可以调用其它的非const成员函数吗?no
4. 非const成员函数内可以调用其它的const成员函数吗?yes
5.static静态成员
一.静态成员基本知识
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。
使用要点:静态成员变量一定要在类外进行初始化
二.静态成员特性
静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
静态成员函数没有隐藏的this指针,不能访问任何非静态成员
静态成员也是类的成员,受public、protected、private 访问限定符的限制
三.静态成员函数和非静态成员函数的调用关系
请思考下面的几个问题:
静态成员函数可以调用非静态成员函数吗?no(无this指针)
非静态成员函数可以调用类的静态成员函数吗? yes