6 继承
6.1继承的基本语法
例如我们看到很多网站中,都有公共的头部,公共的底部,甚至公共的左侧列表,只有中心内容不同,接下来我们分别利用普通写法和继承的写法来实现网页中的内容,看一下继承存在的意义以及好处。
#include<iostream>
using namespace std;
//继承实现页面 这个是三个学科都共同拥有的部分
class basepage
{
public:
void header()
{
cout << "首页、公开课、登录、注册...(公共头部)" << endl;
}
void footer()
{
cout <<"帮助中心、交流合作、站内地图...(公共底部)" << endl;
}
void left()
{
cout << "JAVA、Python、c++...(公共分类列表)" << endl;
}
};
//继承好处 : 减少重复代码
//语法: class 子类 : 继承方式 父类
//子类 也称为 派生类
//父类 也称为 基类
//java页面
class java :public basepage //语法切记
{
public:
void content()
{
cout <<"java学科视频" << endl;
}
};
//python页面
class python :public basepage
{
public:
void content()
{
cout <<"python学科视频" << endl;
}
};
//c++页面
class cpp :public basepage
{
public:
void content()
{
cout << "cpp学科视频" << endl;
}
};
void test01()
{
cout << "java 下载视频页面如下" << endl;
java ja;
ja.content();
ja.footer();
ja.header();
ja.left();
cout << " _________________________________________________" << endl;
cout << "python 下载视频页面如下" << endl;
python py;
py.content();
py.footer();
py.header();
cout << " _________________________________________________" << endl;
py.left(); cout << "java 下载视频页面如下" << endl;
cpp cp;
cp.content();
cp.footer();
cp.header();
cp.left();
}
int main() {
test01();
system("pause");
return 0;
}
6.2 继承方式
继承的语法:class子类∶继承方式父类
继承方式—共有三种:
公共继承 保护继承 私有继承
太简单了,三种权限,不同调用的时候都有不同的访问权限,记住即可。
#include<iostream>
using namespace std;
//继承方式
class base1 //三种变量
{
public:
int m_a;
protected:
int m_b;
private:
int m_c;
};
//公共继承
class son1 : public base1
{
public:
void func()
{
m_a = 10; //父类中的公共权限成员到子类中依然是公共权限
m_b = 10; //保护权限的成员也可以的
//m_c = 10; //私有没有权限了!!
}
};
void test01()
{
son1 s1;
s1.m_a = 100;
//s1.m_b = 100; //虽然可以修改保护成员,但是类外不可以访问protected的成员。
}
//保护继承
class son2 : protected base1
{
public:
void func()
{
m_a = 10; //父类中的保护权限成员到子类中依然是公共权限
m_b = 10; //保护权限的成员也可以的
//m_c = 10; //私有没有权限了!!
}
};
void test02()
{
son2 s2;
//s2.m_a = 100;//类外不可以访问protected的成员。
//s1.m_b = 100; //类外不可以访问protected的成员。
}
//私有继承
class son3 : private base1
{
public:
void func()
{
m_a = 10; //私有权限
m_b = 10; //私有权限
//m_c = 10; //父类的私有你就没有权限了!!
}
};
void test03()
{
son3 s3;
//s3.m_a = 100;//类外不可以访问protected的成员。
//s3.m_b = 100; //类外不可以访问protected的成员。
}
int main() {
test03();
system("pause");
return 0;
}
6.3 继承中的对象模型
问题: 从父类继承过来的成员,哪些属于子类对象中?
#include<iostream>
using namespace std;
//
class base1
{
public:
int m_a;
protected:
int m_b;
private:
int m_c;
};
class son : public base1
{
public:
int m_d;
};
//利用开发人员命令提示工具查看对象模型
//跳转盘符 F:
// 跳转文件路径 cd 具体路径下
// 查看命名
//cl /d1 reportSingleClassLayout类名 文件名
//
void test01()
{
//16
//父类中的所有非静态成员属性都会被子类继承下去
//父类中私有成员属性, 是被编译器隐藏了,因此是访问不到的,但是确实是被继承下去了
cout <<sizeof(son) <<endl;
}
int main() {
test01();
system("pause");
return 0;
}
6.4 继承中构造和析构顺序
子类继承父类后,当创建子类对象,也会调用父类的构造函数
问题:父类和子类的构造和析构顺序是谁先谁后?
#include<iostream>
using namespace std;
//
class base
{
public:
base()
{
cout << "base构造函数" << endl;
}
~base()
{
cout << "base析构函数" << endl;
}
};
class son : public base
{
public:
son()
{
cout << "son构造函数" << endl;
}
~son()
{
cout << "son析构函数" << endl;
}
};
void test01()
{
//base b;
//继承中的构造和析构顺序如下:
//先构造父类,再构子类;析构相反
son s;
}
int main() {
test01();
system("pause");
return 0;
}
6.5 继承同名成员处理方式
问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢?
·访问子类同名成员直接访问即可
·访问父类同名成员需要加作用域
#include<iostream>
using namespace std;
//
class base
{
public:
base()
{
m_a = 100;
}
void func()
{
cout <<"base - func()" << endl;
}
void func(int a)
{
cout << "base (int a) - func()" << endl;
}
int m_a;
};
class son :public base
{
public:
son()
{
m_a = 200;
}
void func()
{
cout << "son - func()" << endl;
}
int m_a;
};
//同名成员属性处理方式
void test01()
{
son s;
cout <<"son m_a = " <<s.m_a << endl;
//如果通过子类对象 访问到父类中同名成员 需要加上父类的作用域
cout << "base m_a = " << s.base::m_a << endl;
}
//同名成员函数处理方式
void test02()
{
son s;
s.func(); //直接调用,调用的是子类的同名成员
//怎么调用父类的同名成员函数?????
s.base::func();
//如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类的所有的同名成员函数;要加作用域
s.base::func(100);
}
//总结
//子类对象可以直接访问到子类中同名成员
//子类对象加作用域可以访问到父类的同名成员
//如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类的所有的同名成员函数;要加作用域
int main() {
test02();
system("pause");
return 0;
}
6.6 继承同名静态成员处理方式
问题:继承中同名的静态成员在子类对象上如何进行访问?
静态成员和非静态成员出现同名,处理方式—致
访问子类同名成员直接访问即可
访问父类同名成员需要加作用域
#include<iostream>
using namespace std;
//
class base
{
public:
static int m_a;
static void func()
{
cout << "base - static void func()" << endl;
}
static void func(int a)
{
cout << "base(int a) - static void func()" << endl;
}
};
int base::m_a = 100;
class son : public base
{
public:
static int m_a;
static void func()
{
cout << "son - static void func()" << endl;
}
};
int son::m_a = 200;
//同名静态成员属性
void test01()
{
//静态成员访问方式有两种
//1 通过对象访问
cout << "通过对象访问" << endl;
son s;
cout <<"son 下m_a =" <<s.m_a << endl;
cout << "base 下m_a =" << s.base::m_a << endl;
//2 通过类名访问
cout << "通过类名访问" << endl;
cout << "son 下m_a =" << son::m_a << endl;
cout << "base 下m_a =" << son::base::m_a << endl; //第一个双冒号,代表通过类名方式访问 第二个代表访问父类的作用域下
}
//同名静态成员函数
void test02()
{
//1 通过对象访问
cout << "通过对象访问" << endl;
son s;
s.func();
s.base::func();
//2 通过类名访问
cout << "通过类名访问" << endl;
son::func();
son::base::func();
son::base::func(100);
}
int main() {
test02();
system("pause");
return 0;
}
6.7 多继承语法
C++允许一个类继承多个类
语法:class子类︰继承方式父类1 ,继承方式父类2…
多继承可能会引发父类中有同名成员出现,需要加作用域区分
#include<iostream>
using namespace std;
//
class base1
{
public:
base1()
{
m_a = 100;
}
int m_a;
};
class base2
{
public:
base2()
{
m_a = 100;
}
int m_a;
};
//子类继承base1和base2
class son : public base1, public base2
{
public:
son()
{
m_c = 300;
m_d = 400;
}
int m_c;
int m_d;
};
void test01()
{
son s;
cout << "sizeof son"<<sizeof(s) << endl;
//当父类中出现同名成员,需要加作用域区分
cout << "base1 m_a = " << s.base1::m_a << endl;
cout << "base2 m_a = " << s.base2::m_a << endl;
}
int main() {
test01();
system("pause");
return 0;
}
6.8 菱形继承
菱形继承问题:
1.羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据时,就会产生二义性。
⒉草泥马继承自动物的数据继承了两份,其实我们应该清楚,这份数据我们只需要一份就可以。
#include<iostream>
using namespace std;
//动物类
class animal
{
public:
int m_age;
};
//利用虚继承 可以解决菱形继承的问题
// 在继承之前 加上关键字 virtual 变成虚继承
// animal 类 称为 虚基类
//
//羊
class sheep :virtual public animal {};
//驼
class tuo : virtual public animal {};
//羊驼类
class sheeptuo : public sheep, public tuo {};
void test01()
{
sheeptuo st;
st.sheep::m_age = 19;
st.tuo::m_age = 15;
//当菱形继承,两个父类拥有相同数据,需要加以作用域区分
cout << "sheep m_age = " << st.sheep::m_age << endl;
cout << "tuo m_age = " << st.tuo::m_age << endl;
cout << "st m_age = " << st.m_age << endl;
//但是我们中的,我们只需要一份就可以了,菱形继承导致数据有两份,资源浪费
}
int main() {
test01();
system("pause");
return 0;
}
7 多态
多态是C++面向对象三大特性之一多态分为两类
静态多态 | 动态多态 |
---|---|
函数重载和运算符重载属于静态多态,复用函数名 | 派生类和虚函数实现运行时多态 |
静态多态的函数地址早绑定–编译阶段确定函数地址 | 动态多态的函数地址晚绑定运行阶段确定函数地址 |
#include<iostream>
using namespace std;
//多态
//动物类
class Animal
{
public:
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
//猫类
class Cat : public Animal
{
public:
//重写 函数返回值类型 函数名 参数列表 要完全相等
void speak() //virtual 可加可不加
{
cout << "小猫在说话" << endl;
}
};
//狗类
class Dog : public Animal
{
public:
void speak()
{
cout << "小狗在说话" << endl;
}
};
//执行说话的函数
//地址早绑定的话,只会输出动物在说话,因为在编译阶段 animal.speak();确定函数地址
//若想执行让猫说话,那么这个函数地址就不可以提前绑定,需要在运行阶段绑定,地址晚绑定 ,virtual void speak()这样就可以了
//动态多态满足条件
//1. 有继承关系
//2. 子类要重写父类的虚函数
//动态多态的使用
//父类的指针或者引用 执行子类的对象
void dospeak(Animal &animal) //Animal &animal = cat
{
animal.speak();
}
void test01()
{
Cat cat;
dospeak(cat);
Dog dog;
dospeak(dog);
}
int main() {
test01();
system("pause");
return 0;
}
7.1 多态的基本概念
#include<iostream>
using namespace std;
//多态
//动物类
class Animal
{
public:
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
//猫类
class Cat : public Animal
{
public:
//重写 函数返回值类型 函数名 参数列表 要完全相等
void speak() //virtual 可加可不加
{
cout << "小猫在说话" << endl;
}
};
//狗类
class Dog : public Animal
{
public:
void speak()
{
cout << "小狗在说话" << endl;
}
};
//执行说话的函数
//地址早绑定 在编一阶段确定函数地址
//若想执行让猫说话,那么这个函数地址就不可以提前绑定,需要在运行阶段绑定,地址晚绑定
//动态动态满足条件
//1. 有继承关系
//2. 子类要重写父类的虚函数
//动态多态的使用
//父类的指针或者引用 执行子类的对象
void dospeak(Animal& animal) //Animal &animal = cat
{
animal.speak();
}
void test01()
{
Cat cat;
dospeak(cat);
Dog dog;
dospeak(dog);
}
void test02()
{
cout << "sizeof(Animal)" << sizeof(Animal) << endl; //指针的大小
}
int main() {
test02();
system("pause");
return 0;
}
7.2 多态案例─计算器类
案例描述:
分别利用普通写法和多态技术,设计实现两个操作数进行运算的计算器类
多态的优点:│
代码组织结构清晰·可读性强
利于前期和后期的扩展以及维护
#include<iostream>
using namespace std;
//普通实现
class calculate
{
public:
int getresult(string oper)
{
if (oper == "+")
{
return m_num1 + m_num2;
}
else if (oper == "-")
{
return m_num1 - m_num2;
}
else if (oper == "*")
{
return m_num1 * m_num2;
}
}
//如果要扩展修改功能,需要修改源码
//在真实开发中 提倡 开闭原则
//开闭原则 : 对拓展进行开放,对修改进行关闭
int m_num1;
int m_num2;//操作数
};
void test01()
{
//创建计算器对象
calculate c;
c.m_num1 = 10;
c.m_num2 = 10;
cout << c.m_num1 << "+" << c.m_num2 << "=" << c.getresult("+") << endl;
cout << c.m_num1 << "-" << c.m_num2 << "=" << c.getresult("-") << endl;
cout << c.m_num1 << "*" << c.m_num2 << "=" << c.getresult("*") << endl;
}
// 多态实现计算器!!!!!!!!!
// 好处: 1 组织结构清晰
// 2 可读性强
// 3 对于前期和后期扩展以及维护性高
//实现计算器的抽象类
class abstractclaculator
{
public:
virtual int getresult()
{
return 0;
}
int m_num1;
int m_num2;
};
//加法计算器类
class addcalculator : public abstractclaculator
{
public:
int getresult()
{
return m_num1 + m_num2;
}
};
//减法计算器类
class subcalculator : public abstractclaculator
{
public:
int getresult()
{
return m_num1 - m_num2;
}
};
//加法计算器类
class mulcalculator : public abstractclaculator
{
public:
int getresult()
{
return m_num1 * m_num2;
}
};
void test02()
{
//多态使用条件
//父类指针或者引用指向子类对象
//加法运算
abstractclaculator* abc = new addcalculator; //new一个对象
abc->m_num1 = 100;
abc->m_num2 = 100;
cout << abc->m_num1 << "+" << abc->m_num2 << "=" << abc->getresult() << endl;
//new的堆区数据,手动销毁,堆区数据,指针类型没变
delete abc;
//减法运算
abc = new subcalculator; //new一个对象
abc->m_num1 = 100;
abc->m_num2 = 100;
cout << abc->m_num1 << "-" << abc->m_num2 << "=" << abc->getresult() << endl;
delete abc;
//乘法运算
abc = new mulcalculator; //new一个对象
abc->m_num1 = 100;
abc->m_num2 = 100;
cout << abc->m_num1 << "*" << abc->m_num2 << "=" << abc->getresult() << endl;
delete abc;
}
int main() {
test02();
system("pause");
return 0;
}
7.3 纯虚函数和抽象类
在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容
因此可以将虚函数改为纯虚函数
纯虚函数语法:virtual返回值类型函数名(参数列表)= 0 ;
当类中有了纯虚函数,这个类也称为抽象类
抽象类特点:
1 无法实例化对象。2 子类必须重写抽象类中的纯虚函数,否则也属于抽象类
#include<iostream>
using namespace std;
//
class base
{
public:
//纯虚函数
//只要有一个纯虚函数,这个类就成为抽象类
//抽象类特点:
//1. 无法实例化对象
//2. 抽象类的子类 必须要重写父类中的纯虚函数 否则也属于抽象类
virtual void func() = 0;
};
class son :public base
{
public:
virtual void func() {
cout <<"func函数的调用" << endl;
}
};
void test01()
{
//base b; //战区,不允许
//new base; //堆区也不可以
//son s;//子类必须重写父类的纯虚函数,否则无法实例化对象
base* base = new son;
base->func();
}
int main() {
test01();
system("pause");
return 0;
}
7.4 多态案例二-制作饮品
创建制作流程的虚函数,然后制作咖啡和制作茶叶分别对过程进行改造,输出即可。
#include<iostream>
using namespace std;
//
class abstractdrinking
{
public:
//煮水
virtual void boil() = 0;
//冲泡
virtual void brew() = 0;
//倒入杯子中
virtual void pourincup() = 0;
//加入辅助作料
virtual void putsomething() = 0;
//制作饮品
void makedrink()
{
boil();
brew();
pourincup();
putsomething();
}
};
//制作咖啡
class coffee : public abstractdrinking
{
//煮水
virtual void boil()
{
cout << "煮农夫山泉" << endl;
}
//冲泡
virtual void brew()
{
cout << "冲泡咖啡" << endl;
}
//倒入杯子中
virtual void pourincup()
{
cout << "倒入杯中" << endl;
}
//加入辅助作料
virtual void putsomething()
{
cout << "加入糖和牛奶" << endl;
}
};
//制作茶叶
class tea : public abstractdrinking
{
//煮水
virtual void boil()
{
cout << "煮自来水" << endl;
}
//冲泡
virtual void brew()
{
cout << "冲泡茶叶" << endl;
}
//倒入杯子中
virtual void pourincup()
{
cout << "倒入玻璃杯中" << endl;
}
//加入辅助作料
virtual void putsomething()
{
cout << "加入柠檬,枸杞" << endl;
}
};
//制作函数
void dowork(abstractdrinking * abs) //abstractdrinking * abs = new coffee 父类的指针指向子类的对象
{
abs->makedrink();
delete abs; //手动开辟,手动释放
}
void test01()
{
//制作咖啡
dowork(new coffee);
//制作茶叶
cout << "_______________________茶叶制作" << endl;
dowork(new tea);
}
int main() {
test01();
system("pause");
return 0;
}
7.5 虚析构和纯虚析构
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方式:将父类中的析构函数改为虚析构或者纯虚析构
虚析构和纯虚析构共性: 可以解决父类指针释放子类对象·都需要有具体的函数实现
虚析构和纯虚析构区别: 如果是纯虚析构,该类属于抽象类,无法实例化对象
#include<iostream>
using namespace std;
//
class animal
{
public:
animal()
{
cout << "animal构造函数调用" << endl;
}
//利用虚析构可以解决 父类指针释放子类对象时不干净的问题
// virtual ~animal()
// {
// cout << "animal析构函数调用" << endl;
// }
//纯虚析构,需要声明也需要函数的实现。
//有了纯虚析构之后,这个类也属于抽象类,无法实例化对象
virtual ~animal() = 0;
//纯虚函数
virtual void speak() = 0;
};
animal:: ~animal()
{
cout << "animal纯虚析构函数调用" << endl;
}
class cat : public animal
{
public:
cat(string name)
{
cout << "cat构造函数调用" << endl;
m_name = new string(name);
}
void speak()
{
cout <<*m_name<< "小猫在说话" << endl;
}
~cat()
{
if (m_name != NULL)
{
cout<<"cat析构函数调用" << endl;
delete m_name;
m_name = NULL;
}
}
string* m_name;
};
void test01()
{
animal* animal = new cat("tom");
animal->speak();
//父类指针在西沟时候 不会调用子类的析构函数,导致子类如果有堆区属性,会出现内存泄漏
delete animal;
}
int main() {
test01();
//总结:
// 1.虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
// 2.如果子类中没有堆区数据,可以不写为虚析构或纯虚析构
// 3.拥有纯虚析构函数的类也属于抽象类
system("pause");
return 0;
}
7.6 多态案例三-电脑组装
电脑主要组成部件为CPU (用于计算),显卡(用于显示),内存条(用于存储)
将每个零件封装出抽象基类,并且提供不同的厂商生产不同的零件,例如Intel厂商和Lenovo厂商
创建电脑类提供让电脑工作的函数,并且调用每个零件工作的接口
测试时组装三台不同的电脑进行工作
#include<iostream>
using namespace std;
//抽象不同零件类
//抽象cpu类
class CPU
{
public:
//抽象计算函数
virtual void calculate() = 0;
};
//抽象显卡类
class Videocard
{
public:
//抽象计算函数
virtual void display() = 0;
};
//抽象内存条类
class Memory
{
public:
//抽象计算函数
virtual void storage() = 0;
};
//电脑类
class Computer
{
public:
Computer(CPU* cpu, Videocard* vc, Memory* mem) //接收指针
{
m_cpu = cpu;
m_mem = mem;
m_vc = vc;
}
//提供工作的指针
void work()
{
//让零件工作起来,调用接口
m_cpu->calculate();
m_vc->display();
m_mem->storage();
delete m_cpu, m_mem, m_vc;
}
private:
CPU* m_cpu; //CPU的零件指针
Videocard* m_vc;
Memory* m_mem;
};
//具体厂商
//Intel厂商
class Intelcpu : public CPU
{
public:
void calculate()
{
cout << "Intel的cpu开始计算了" << endl;
}
};
class Intelvideocard: public Videocard
{
public:
void display()
{
cout << "Intel的显卡开始显示了" << endl;
}
};
class Intelmemory : public Memory
{
public:
void storage()
{
cout << "Intel的内存条开始存储了" << endl;
}
};
//Lenovo厂商
class Lenovocpu : public CPU
{
public:
void calculate()
{
cout << "Lenovo的cpu开始计算了" << endl;
}
};
class Lenovovideocard : public Videocard
{
public:
void display()
{
cout << "Lenovo的显卡开始显示了" << endl;
}
};
class Lenovomemory : public Memory
{
public:
void storage()
{
cout << "Lenovo的内存条开始存储了" << endl;
}
};
void test01()
{
//第一台电脑零件
CPU* intercpu = new Intelcpu;
Videocard * intelcard = new Intelvideocard;
Memory* intelmem = new Intelmemory;
//创建第一台电脑
Computer* computer1 = new Computer(intercpu, intelcard, intelmem);
computer1->work();
delete computer1;
//第二台电脑零件
CPU* lenovocpu = new Lenovocpu;
Videocard* lenovocard = new Lenovovideocard;
Memory* lenovomem = new Lenovomemory;
cout << "第二台电脑——————————————————————————" << endl;
//第二台电脑组装
Computer* computer2 = new Computer(lenovocpu, lenovocard, lenovomem);
computer2->work();
delete computer2;
cout << "第三台电脑——————————————————————————" << endl;
//第三台电脑组装
Computer* computer3 = new Computer(new Lenovocpu, new Intelvideocard, new Lenovomemory);
computer3->work();
delete computer3;
}
int main() {
test01();
system("pause");
return 0;
}
8 文件操作
8.1文本文件,写文件
程序运行时产生的数据都属于临时数据,程序—旦运行结束都会被释放通过文件可以将数据持久化
C++中对文件操作需要包含头文件< fstream >
文件类型分为两种:
1.文本文件-文件以文本的ASCII码形式存储在计算机中
2.二进制文件-文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们
操作文件的三大类:1.ofstream:写操作2. ifstream:读操作3. fstream :读写操作
#include<iostream>
using namespace std;
#include <fstream>
//
void test01()
{
//1. 包含头文件 fstream
//2. 创建流对象 ofstream写操作代码
ofstream ofs;
//3. 指定打开方式
ofs.open("test.txt", ios::out);
//4. 写内容
ofs << "姓名:张三" << endl; //左移运算符向文件写入数据
ofs << "性别:男" << endl;
ofs << "年龄:18" << endl;
//5. 关闭文件
ofs.close();
}
int main() {
test01();
system("pause");
return 0;
}
8.2 文本文件,读文件
#include<iostream>
using namespace std;
#include <fstream>
#include <string>
//
void test01()
{
//1. 包含头文件 fstream
//2. 创建流对象 ifstream写操作代码
ifstream ifs;
//3. 打开文件,并且判断是否打开成功
ifs.open("test.txt", ios::in);
if (!ifs.is_open())
{
cout<< "文件打开失败" << endl;
return; //return后面什么不加表示结束程序
}
//4. 读数据
//第一种
char buf[1024] = {0}; //表示定义了一个大小为1024的char数组,并将所有元素赋值为0。
while (ifs >> buf)
{
cout << buf<<endl;
}
//第二种
char buf[1024] = { 0 };
while (ifs.getline(buf, sizeof(buf)))
{
cout << buf << endl;
}
//第三种
string buf;
while (getline(ifs, buf))
{
cout << buf << endl;
}
//第四种
char c;//一个一个字符读出来,放到c中
while ((c = ifs.get() != EOF)) //get每次读一个字符放到c里面
//EOF end of file ,判断是否读到文件尾部
//5. 关闭文件
ifs.close();
}
int main() {
test01();
system("pause");
return 0;
}
8.3 二进制文件,写文件
以二进制的方式对文件进行读写操作打开方式要指定为ios:binary
二进制方式写文件主要利用流对象调用成员函数write
函数原型:ostream& write(const char * buffer,int len);
参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数
#include<iostream>
using namespace std;
#include <fstream>
#include <string>
//
class person
{
public:
char m_name[64];
int m_age;
};
void test01()
{
//1. 包含头文件 fstream
//2. 创建流对象
ofstream ofs;
//3. 指定打开方式
ofs.open("person.txt", ios::out | ios::binary); //ios::binary二进制写文件的时候必须要加的
//4. 写内容
person p = { "张三",19 };
ofs.write((const char *)&p, sizeof(person));
//5. 关闭文件
ofs.close();
}
int main() {
test01();
system("pause");
return 0;
}
8.4 二进制文件,读文件
二进制方式读文件主要利用流对象调用成员函数read
*函数原型:istream& read(char buffer ,int len);
参数解释 l 字符指针buffer指向内存中一段存储空间。len是读写的字节数
#include<iostream>
using namespace std;
#include <fstream>
#include <string>
//
class person
{
public:
char m_name[64];
int m_age;
};
void test01()
{
//1. 包含头文件 fstream
//2. 创建流对象
ifstream ifs;
//3. 打开文件。判断文件是否打开成功
ifs.open("person.txt", ios::in | ios::binary); //ios::binary二进制写文件的时候必须要加的
if (!ifs.is_open())
{
cout <<"文件打开失败" << endl;
return;
}
//4. 读内容
person p;
ifs.read((char*)&p, sizeof(person));
cout <<"姓名" <<p.m_age <<"年龄" <<p.m_name <<endl;
//数据的地址,数据占用的空间
//5. 关闭文件
ifs.close();
}
int main() {
test01();
system("pause");
return 0;
}