函数
函数默认参数
形参列表中的形参可以有默认值,实参优先。
有默认值的形参堆在后面。声明和实现只能有一个有默认值。
Int func(int a, int b = 10) { }
函数占位参数
数据类型 函数名(数据类型){ }
数据类型 函数名(数据类型 = 默认值){ }
函数重载
函数名可以相同:同一个作用域(全局作用域),但参数不同。
类和对象
C++面向对象三大特征:封装,继承,多态
对象--> 属性(变量)+行为(函数) 可以通过行为向属性赋值
对象集合---类
1 对象的初始化和清理
1.1 构造函数和析构函数
构造函数——初始化
析构函数——销毁
这两个函数又编译器自动调用。如果我们不提供,编译器会提供,但编译器提供的是空实现。
构造函数:类名(){}
析构函数:~类名(){}
1.2 构造函数的分类及调用
两种分类方式:有参构造/无参构造-------普通构造/拷贝构造
三种调用方式:括号法、显示法、隐式转换法
深拷贝:简单的复制拷贝操作。 解决浅拷贝带来的堆区内存重复释放的问题
浅拷贝:在堆区重新申请空间,进行拷贝操作。 会导致堆区的内存重复释放
1.3 类对象作为类成员
先构造Phone,再Person
先析构Person,再Phone
2 对象模型和this指针
类内的成员变量和成员函数分开存储
只有非静态成员变量才属于类的对象。
this指针指向被调用的成员函数所属的对象。
1)解决名称冲突-----规范命名
2)返回对象本体,用&接收
常函数:成员函数后加const的函数称为常函数。
常函数内的成员属性不能修改。
若要修改,成员属性声明时加关键字mutable
常对象:声明对象前加const。
常对象只能调用常函数。
3 友元
让一个函数或者类访问另一个类中私有成员
friend
三种实现:1.全局函数。2.类。3.成员函数
4 运算符重载
4.1 ➕运算符重载
重新定义运算符
实现两个自定义数据类型相加的运算
operator+ Person p3 = p1.operater+(p2); 等价于 Person p3 = p1 + p2;
4.2 左移运算符重载
可以输出自定义数据类型
4.3 递增运算符重载
实现自定义的整型数据
4.4 复制运算符重载
编译器至少给一个类默认添加4个函数:默认构造,默认析构,默认拷贝,赋值运算符 operator=
存在深浅拷贝问题
4.5 关系运算符重载
比较两个自定义的数据类型
4.6 函数调用运算符重载
函数调用运算符——()。 仿函数
5 继承
封装 继承 多态
继承——减少重复代码
语法----> class 子类:继承方式 父类 class Java: public base {}
5.1 继承方式
1.公共。 【父public -> 子public】【父protected -> 子protected】 【父private 不可访问】
2.保护。 public和protected都变成protected,private不可访问
3.私有。 public和protected都变成private,private不可访问
5.2 同名成员
访问子类同名成员:直接访问 cout<<s1.m_A<<endl;
访问父类同名成员:加作用域 cout<<s1.Base::m_A<<endl;
5.3 多继承和菱形
class 子类:继承方式 父类1,继承方式 父类2 ------>可能出现同名成员,需要加作用域
菱形继承:羊和驼 继承了 动物,羊驼 继承了 羊和驼
菱形继承的两个问题:1.羊驼使用羊和驼的数据时会产生二义性。====== 加作用域
2.羊驼继承了两份数据,但实际上仅需要一份。===== 虚继承 virtual
6 多态
静态多态:函数重载和运算符重载均属于静态多态,复用函数名。函数地址早绑定---编译阶段确定函数地址。
动态多态:派生类和虚函数实现运行时多态。函数地址晚绑定---运行阶段确定。
6.1 多态原理
本来一个父类里只有一个函数——sizeof(类) = 1
这个函数变成虚函数后(+virtual)——sizeof(类) = 4 ===== 类的内部结构为一个指针vfpter,指向vftable(存放虚函数表)
v--virtual f--function ptr---pointer table---table
虚函数表内记录虚函数的入口地址。
子类继承了父类的vfpter,指向vftable ====子类为空时
当子类重写了父类虚函数时,子类中的虚函数表内部会替换成子类的虚函数地址====。&Animal::speak 变成了&Cat::speak。======当父类的指针或者引用指向子类对象时,发生了多态
6.2 纯虚函数和抽象类
纯虚函数:virtual 返回值类型 函数名(参数列表)= 0;
当类中有了纯虚函数,这个类也称为抽象类。
抽象类:无法实例化对象。子类必须重写抽象类中的纯虚函数,否则子类也属于抽象类。
文件操作
程序运行时产生的数据都属于临时数据,运行结束后都会被释放,但通过文件可以将数据持久化。
包含头文件<fstream>
文本文件:ascii码
二进制文件:二进制
操作文件:1.ofstream 写操作。2.ifstream 读操作。3.fstream 读写操作。
1 写文件
1.包含头文件 #include <fsteam>
2.创建流对象 ofstream ofs;
3.打开文件 ofs.open("文件路径",打开方式);
4.写数据 ofs <<"写入的数据";
5.关闭文件 ofs.close();
打开方式:ios::in ------为读文件而打开 ios::out --------为写文件而打开
|: ios::in|ios::
2 读文件
1.包含头文件
2.创建流对象 if stream ifs;
3.打开文件 ifs.open("文件路径",打开方式)
4.读数据
5.关闭文件 ifs.close();