1.命名空间
我与官方库、同事的命名 重名 时使用命名空间,使用形如namespace area{ }的命名空间;
例如
如上面的rand虽然定义在全局,但是使用起来会和库中stdilb的rand命名冲突,此时把rand放在命名空间area中并使用域作用限定符::去访问即可
此外命名空间中还可以放入函数和类型;值得注意的是用域作用限定符访问结构体变量时“area::”应放在struct的后面;
rand放在命名空间域后若使用展开命名空间using namespace area; 时rand的所在的命名空间会被打开,此时再次访问rand依旧会出现命名冲突
所以命名空间的展开是会存在一定的危险的;
为了解决此后多次使用某个函数避免重复使用:: 可以针对该函数名对area进行部分展开
值得注意的是这里不能对rand部分展开,否则也会出现声明重复;
此外命名空间还可以嵌套,访问起来如下;
于是便可以了解到常见的using namespcae std 实际上是对c++标准库的展开,展开后例如cout, cin便可以使用了
不同文件中定义同一个命名空间,命名空间会自动合并
2.缺省函数
如图Func是一个初始化为1的形参, 一般函数参数都是无赋值的形参,一旦形参赋值后就会,若main函数中调用该函数时忘记填入了参数, 那么缺省函数便会自使用形参初始化的形参。
若有多个缺省参数,那么函数会从左往右依次给形参赋值
当函数的声明和定义放在不同文件时,不运行缺省参数在声明和定义中同时存在, 其中声明给缺省参数, 定义不给。 下面就是一个错误例子,
修改定义不给缺省参数即可
3. 重载函数
以上是几个函数重载的例子, 其中函数重载不关注返回类型,而是关注参数的个数,类型,顺序等,
函数重载必须在同一个命名空间中:如下面第一张图片中的Computer就无法构成重载
4.引用
一.
引用可以理解为某个变量的别名, 引用和它的引用 的变量共同使用一块空间。
举个例子
这里的b就是变量a的引用(别名)它们共有一块空间, 改变了b,a也会产生相应的改变
又比如C语言中常见的swap函数,采用引用作为参数会比指针更加方便易懂。
此外在单链表中使用引用会显得非常方便易懂:
如果用指针写一个(不带哨兵位)单链表的有关增删查改的函数时,会用到二级指针,否则的话函数内部的指针改变不影响main函数的指针
可是如果使用引用的话
直接传入main函数中的头指针值以及待传入的数据即可。
二.
引用的特性:1.引用 在定义的时候必须初始化,即赋值
2.一个变量可以有多个引用,即一个变量可以有多个别名,这些多个别名和该变量都代表着同一块空间
3.引用一旦引用了一个实体, 该引用不能再引用其他实体
但是引用可以由其他变量赋值
三.
传引用返回的问题:
这里的n随着fun函数的栈帧销毁时而销毁, 在main函数的栈帧和fun函数的栈帧间开辟了一个临时变量存放n的别名的拷贝,但是n所在的空间已经被销毁了, 再去使用n的别名就类似于野指针的使用, 其值可能是1也可能是个随机值。
四
引用和指针的一些对比:
、
(1) 下面这张图是用指针来对一个顺序表第i个位置进行读取和修改
(2)下面这张图是用引用对顺序表的读取和修改
可以看出用指针来写的话要写两个函数, 用引用的话一个函数即完成了读取也实现了修改。
五. 引用权限:引用权限可以平移,可以缩小,但不能放大。
1.权限放大:
使用引用时要注意实体是否被const修饰或者其实体是否是一个常量
如下面的实体被const修饰就不能使用其引用b
还有在使用某些带有返回值但是返回的是临时变量的函数的时候,该返回值被视为常量,如下图的func返回值就不能赋值给引用ret;
此时将ret用const修饰一下即可实现权限平移;
此外在一些数据类型的隐式转换时也会先产生临时变量,例如下面的int i 赋值给double b的时候会先把i拷贝给临时变量,由于临时变量具有常性,所以此时的double b不可以使用引用;
解决办法就是权限平移一下,用const修饰b
5.内联
C语言中的宏的缺点:1.容易出现语法错误,2.不能调试, 3. 无类型安全检查
C语言中的宏的优点: 1.增强代码的复用性, 2.提高性能 , 3.不用建立栈帧
1.内联函数声明和定义不能在两个文件中,
2.内联可以在.h文件中直接定义
3.使用内联不需要建立栈帧
4.内联函数的代码不能太长,否则会出现代码膨胀。
6.类
1.struct和class的默认访问权限不同, struct默认是public, class默认为private;
2.访问限定符不针对类里面的使用, 作用的是main方法使用成员变量或成员函数的时候。
3.类成员中成员函数分配到公共空间, 不占类的内存;
4.类可以声明和定义放在两个文件中写,.h里面写成员变量和成员函数的声明, .cpp文件中写成员函数的定义
5.类中的成员变量往往在前面加_,来区别成员函数中的参数,避免同名。
6.this指针是隐藏的类型指针, 初始化函数void Init(类名* this, int x..)this指针会根据传入的类的地址为该类的成员变量初始化 例如: void Init(类名* this, int x..){this->成员变量1 = x ....}
一.构造函数:
1.构造函数的函数名和类名相同;
2.无返回值;
3.对象实例化时编译器会自动调用对应的构造函数;
4.构造函数可以重载;
5.类名 a1();会报错,无法判读是否是函数声明还是创建类对象, 写成类名 a1即可;
6.构造函数的参数使用缺省参数更加灵活
7.默认构造函数:
1.无参构造
2.全缺省构造
3.自己没有写,编译器自动生成的构造
以上三种默认构造函数只能有一种;
8.编译器生成的默认构造函数的特点:
1.我们不写才会生成,我们写了一个无参构造,或者全缺省构造就不会自动生成了;
2.内置类型成员变量不会处理;
3.自定义类型才会处理,比如struct类型,编译器会回去调用这个成员变量的默认构造函数
二.构析函数:
1.对象销毁时会自动调用构析函数;
2.构析函数无参数无返回值;
3.一个类只能有一个构析函数,所以构析函数不能重载;
4.对象的生命周期结束时, 编译器会自动调用构析函数;
5.后进的先销毁;
7.未写显式构析函数, :1.内置成员变量不处理,2.自定义类型调用其默认构析函数