1 概述
C语言有的、常用的知识点就不再重复了,下面复习一下C++中一些基本且重要的东西
C++的三大特征: 封装、继承、多态
2 函数补充
2.1 函数参数传递
-
值传递:不改变实参,因为在调用时会在栈中分配形参空间,并使用实参初始化形参,然后形参就和实参没有关系了。代码我也就不写了,经典swap(a, b);
-
地址传递:改变实参,传递的是地址,通过解引用访问实参。地址本身还是值传递,但会通过地址去寻找实参并修改实参。
-
引用传递:改变实参,引用就是实参的一个别名,实质是对变量的间接寻址。形参就是实参,声明引用一定要初始化(error),之后不能再改变。在参数传递过程中会给形参分配空间,并用实参初始化它。
2.2 内联函数inline
内联函数的出现是为了减少一些功能简单、规模较小、频繁调用的函数调用开销
内联函数是用于声明的关键字,他只是一种要求,具体是不是内联函数还得编译器说了算。
2.3 带默认形参值的函数
由于参数传递是自右向左的, 因此参数必须自右向左连续定义, 若该参数没有默认参数值, 那么右边参数都不能有参数值
如果在函数声明中定义过默认参数值, 则不能在函数定义中再定义默认参数值, 即使相同也不行
2.4 函数重载
函数名相同 && (返回值不同 || 形参类型不同 || 形参数量不同 || 是否有const)
2.5 函数声明与类型安全
在编译时, 编译器会检查函数声明与函数调用的正确性, 类型会转换, 若不正确会报错
C++比C语言安全, C语言允许对函数不完整声明
如double add();
不是说没有参数, 没有参数要写void, 表示参数未知
3 类与对象
简单的我就快速过了,很多都记得就不一一写了,捡重要不会的写
3.1 类成员的访问控制
访问上public > protected = private 后面再写一下继承那的不同
3.2 类成员函数的内联
隐式声明直接把函数定义放在类中就可以了
```C++ 显式声明
class A
{
pubilc:
int add(int a, int b);
}
inline int A::add(int a, int b)
{
return a + b;
}
```
3.3 构造函数与析构函数
3.3.1 构造函数
创建类对象时自动调用构造函数,编译器会自动生成默认构造函数,什么也不干,如果自己写了构造函数,编译器就不会自动生成了,最好自己再写一个默认构造函数。
3.3.2 复制构造函数
A(const A& a)
形参是对象的引用, 为什么是引用呢?我觉得有两点:第一点最重要,因为如果不是引用,在参数传递过程中还要调用复制构造函数,就死循环了;而就是加快速度吧
自己没写的话,编译器还会给你生成一个默认的复制构造函数,把你类中所有的数据都复制到里面,注意 ! ! 这是浅拷贝
浅拷贝与深拷贝
复制构造函数的调用时机:
-
用一个类的对象初始化另一个类的对象时;
-
函数形参是类的对象,调用函数时,进行形参和实参的拷贝时;
-
函数的返回值是类的对象时;(这个要好好说一下:被调函数中的类对象属于局部变量,在函数结束时就会被销毁,这样怎么传给主调函数呢?这时编译器就先生成一个临时对象(生存期只在函数调用处的那个表达式b = A();,在执行return a;时会调用复制构造函数到临时的无名对象中,函数结束局部变量a销毁,临时无名对象再赋值给b(此时可不是调用复制构造函数哦,这时候调用的是operator=())!
3.3.3 析构函数
在对象销毁时,会自动调用析构函数,~A();没有返回值,没有参数,但可以是虚函数
3.4 类的组合
类的组合就是描述了一个包含与被包含的关系,也就是have a的关系,将一个类对象封装在另一个类中。
3.4.1 组合类
```C++
class A
{
public:
B b;
C c;
A(B bb, C cc):b(bb), c(cc)
{
}
...
}
```
当创建A时,首先要创建B,那么如果A中有多个对象,构造函数的调用顺序是啥样的呢?
-
首先调用内嵌的对象的构造函数,顺序是按照类内的定义顺序,与构造函数的初始化列表顺序无关
-
其次调用本类的构造函数
复制构造函数也是这样的
析构函数调用顺序与构造函数完全相反
3.4.2 前向引用声明
就是说如果内嵌这个类对象还没有定义怎么办?可以现在前面写一个class B;
,不涉及任何定义,仅仅声明
不能相互内嵌类对象
3.5 结构体和联合体
结构体和类差不多,唯一区别在于访问控制,类内默认私有访问,结构体默认公有访问。
C语言中的struct只能有数据成员,不能有函数成员,也没有