文件分类 - 文本文件:ASCII码存储 - 二进制文件:二进制存储

操作文件三大类: -ofstream:写 -ifstream:读 -fstream:读写 ## 写文件 - 需包含头文件#include<fstream> - 创建流对象ofstream ofs; - 打开文件ofs.open("文件路径","打开方式"); - 写数据ofs<<"写入的数据"; - 关闭文件ofs.close();

文件打开方式: |打开方式|作用| |:---|:---| |ios::in|读文件| |ios::out|写文件| |ios::ate|初始位置为文件尾| |ios::app|追加方式写| |ios::trunc|先删除,再创建| |ios::binary|二进制方式写| 可以使用|用多种方式打开:ios::in|ios::out ## 读文件 - 需包含头文件#include<fstream> - 创建流对象ifstream ifs; - 打开文件ifs.open("文件路径","打开方式"); - 读数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//方法一
char buf[1024] = {0};
while (ifs >> buf)
{
cout << buf << endl;
}
//方法二
char buf[1024] = {0};
while (ifs.getline(buf,sizeof(buf)))
{
cout << buf << endl;
}
//方法三
string buf;
while (ifs.getline(buf,sizeof(buf)))
{
cout << buf << endl;
}
//方法四
char c;
while ((c = ifs.get()) != EOF) //EOF: end of file
{
cout << c;
}
-关闭文件ifs.close();

二进制文件读写

写文件: ofs.write((const char *)&p, sizeof(p)); 读文件: ifs.read((char *)&p, sizeof(p)));

分类:

静态多态:重载(早绑定,编译阶段确定函数地址) 动态多态:派生类和虚函数实现运行时多态(晚绑定,运行阶段确定函数地址) ## 虚函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class RNG
{
public:
virtual void FW()
{
cout << "RNG不行" << endl;
}
};
class XiaoHu: public RNG
{
virtual void FW()
{
cout << "Xiaohu不行" << endl;
}
};
void print(RNG& rng)
{
rng.FW();
}
void test_vir()
{
XiaoHu LYH;
print(LYH); //输出"Xiaohu不行"
}
## 多态好处: 1、组织结构清晰 2、可读性强 3、利于前期和后期拓展以及维护 ## 纯虚函数和抽象类: 父类中的虚函数一般无意义,所以可以简写成纯虚函数 带纯虚函数的类称为抽象类 语法:virtual 返回值类型 函数名 (参数列表) = 0 特点:无法实例化对象 ## 虚析构和纯虚析构 如果子类中有属性开辟到堆区,父类指针释放时无法调用到子类的析构代码 因此,需要将父类的析构函数改为虚析构 特点: 1、可以解决父类指针释放子类对象 2、需要有具体的函数实现 纯虚析构需要定义,也需要实现

运算符重载:采用operator对运算符进行重新定义,本文将对+、++、<<、=、==进行示例,其余运算符可推。 ## 重载加号运算符 加号运算符可以采用成员函数、全局函数两种方式重载。 成员函数重载+:

1
2
3
4
5
6
person operator+(person &per)
{
person temp;
temp.m_A = this->m_A + per.m_A;
return temp;
}
全局函数重载+:
1
2
3
4
5
6
person operator+(person& p1, person& p2)
{
person temp;
temp.m_A = p1.m_A + p2.m_A;
return temp;
}
## 重载递增运算符 在C++中,++符号位于变量前和变量后含义不同,因此需要区分。 成员函数重载前置++:
1
2
3
4
5
person &operator++()//前置返回引用才能嵌套
{
m_A++;
return *this;
}
成员函数重载后置++:
1
2
3
4
5
6
person operator++(int)//后置需要占位参数
{
person temp = *this;
m_A++;
return temp;
}
## 重载左移运算符 类变量不可直接输出,通过重载左移运算符可直接通过cout输出对象:
1
2
3
4
5
ostream &operator<<(ostream &cout, person5 p) //返回引用
{
cout << p.m_A;
return cout;
}
## 重载赋值运算符 编译器提供的=只能进行浅拷贝,如果需要深拷贝则需要重载=运算符:
1
2
3
4
5
6
7
8
9
10
11
12
person &operator=(person &p)
{
//判断是否有属性在堆区,有则清干净
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//深拷贝
m_Age = new int(*p.m_Age);
return *this;
}
## 重载关系运算符
1
2
3
4
5
bool operator==(person p)
{
if (p.m_Name == m_Name && p.m_Age == m_Age) return true;
else return false;
}
## 仿函数 可以通过重载()来产生仿函数,譬如:
1
2
3
4
void operator()(string str)
{
cout << str << endl;
}
可通过变量名("输出内容");来输出字符串。 仿函数的应用非常灵活,在此无法一一列举。

构造函数与析构函数

构造函数形式为与类同名,用于初始化对象; 析构函数形式为~类名(),用于清理对象 ## 默认构造函数 默认构造函数没有参数,若没有自定义构造函数,则类自动提供一个空的默认构造函数。

1
2
3
4
5
person()
{
m_age = 0;
m_height = NULL;
}
## 自定义构造函数 通过自定义构造函数来初始化对象,可以提供参数
1
2
3
4
5
person(int a, int height)//构造函数,实例化时自动调用,用于初始化  普通&拷贝,无参&有参。
{
m_age = a;
m_height = new int(height);
}
也可简写:peoson(int a,int b):m_age(a),m_height(b){} ## 拷贝构造函数 编译器默认提供,但若有属性在堆区则需要深拷贝
1
2
3
4
5
person(const person& p)//拷贝构造函数(默认提供)
{
//深拷贝(在堆区重新申请空间,进行拷贝操作,有属性在堆区开辟时需使用)
m_height = new int(*p.m_height);
}
使用深拷贝需要自定义析构函数进行清理
1
2
3
4
5
6
7
8
~person()//析构函数,对象销毁前自动调用,用于清理(默认提供)
{
if (m_height != NULL)//深拷贝析构
{
delete m_height;
m_height = NULL;
}
}

内存四区

程序运行前就存在:代码区、全局区 程序运行后存在:栈区、堆区 代码区:存放cpu执行的机器指令,共享的、只读的 全局区:存放全局变量、静态变量、字符串常量,程序结束后系统自动释放 栈区:存放函数参数、局部变量等,函数执行完后自动释放 堆区:程序员分配释放,若不释放程序结束后系统自动释放。一般用new开辟,用delete释放:

1
2
3
4
int* p = new int(10);
delete p;
int* arr = new int[10]; //创建数组
delete[] arr;
## 引用 采用 &来生成一个引用
1
2
int num = 10;
int &b = num; //引用必须初始化,且地址不可再更改
常量引用:用来修饰形参,防止误操作
1
const int& ref = num;  //ref的值不可修改
引用作参数,可修改实参:
1
2
3
void swap(int& a, int& b)//引用作参数,可修改实参
{
}

一、定义

指针:用来存放变量地址(起始地址)的变量(间接访问)。 引用操作符&:获取一个变量的地址值; 解引用操作符*:获取一个地址对应的数据;

1
2
3
4
5
int i = 5;
int *i_pointer = &i; //定义一个指针变量,32位下占4字节
printf("%d", i); //直接访问,输出5
printf("%d", *i_pointer); //间接访问,输出5
printf("%d", i_pointer); //输出i所在的地址
## 二、使用场景 ### 1.传递 函数定义时使用变量地址:
1
2
3
4
void(int *j)
{
*j = 5; //*j等价于变量i
}
函数调用时传递变量地址:
1
change(&i); //j=&i
### 2.偏移 根据指针加减偏移量形成新的地址
1
2
3
4
5
6
7
int a[5]={1,2,3,4,5};//数组名a存储了其起始地址
int *p;
p = a;
for (int i=0;i<5;i++)
{
printf("%d",*(p+i)); //输出a[i]的值
}
数组名作为实参传递给子函数时,弱化为指针
1
2
3
4
5
6
7
8
9
10
11
12
void change(char *d)
{
*d = 'H';
d[1] = 'E';
*(d+2) = 'L';
}
int main()
{
char c[10] = "hello";
change(c); //变为HELlo
return 0;
}
## 三、指针与动态内存申请malloc C头文件:stdlib.h
1
2
3
4
5
6
int size=20; //需要申请的字节数
char *p;
p = (char*)malloc(size); //在堆区申请20字节空间,malloc返回无类型指针void*,需要强制转换
strcpy(p,"malloc success");
puts(p); //输出malloc success
free(p); //用完记得释放

标题

#表示一级标题,##表示二级标题

代码块

代码块用三个反引号```括起来,譬如:

1
2
3
4
``` c++
int main()
{
}

表格

1
2
3
|姓名|年龄|成绩|         //用 | 分隔
|:---|---:|:---:| //:表示文字位置
|张三|19|60|

分割线

三条短横---代表分割线

超链接

链接描述,如:

1
[百度](https://baidu.com)

字体

1
2
3
4
*斜体*
**加粗**
``行内代码``
<u>下划线</u>

插入图片

图片
0%