1.内存分区模型:
C++程序在执行时,将内存大方向划分为四个区域
(1)代码区:存放函数体的二进制代码,由操作系统进行管理
(2)全局区:存放全局变量和静态变量以及变量
(3)栈区:由编译器自动分配释放,存放函数的参数值,局部变量等
(4)堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
四区的意义:不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程
在程序运行前:
生成了exe可执行程序,未执行该程序前分为两个区域
代码区:
存放CPU执行的机器指令
代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令
全局区:
全局变量和静态变量存放在此
全局区还包含了常量区,字符串常量和其他常量也存放在此
该区域的数据在程序结束后由操作系统释放
栈区:
由编译器自动分配释放,存放函数的参数值,局部变量等
注意事项:不要返回局部变量的地址
形参数据也会放在栈区
堆区:
由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
在C++中主要利用new在堆区开辟数据
#include<iostream>
using namespace std;int* func()
{//利用new关键字,将数据开辟到堆区int* p = new int(10);return p;
}
//这里函数中的p被释放之前,把地址传给了main中的P,以访问堆区的10
int main()
{//在堆区开辟数据int* p = func();//10 10 地址cout << *p << endl;cout << *p << endl;cout << &p << endl;system("pause");return 0;
}
new操作符:
#include<iostream>
using namespace std;int* func()
{//在堆区创建整型数据//new返回的是 该数据类型的指针int* p = new int(10);return p;
}
void test01()
{int* p = func();cout << *p << endl;cout << *p << endl;cout << *p << endl;//堆区的数据由程序员管理//利用关键字delete释放delete p;//cout << *p << endl;该操作会报错,内存已经被释放
}
//利用new开辟堆区的数组
void test02()
{//创建10个整型的数组,返回数组的首元素地址int *arr =new int[10];//arr就变成了数组名arr[1] = 1;//释放数组需要加一个中括号delete[]arr;
}
int main()
{test01();system("pause");return 0;
}
2.引用
基本用法:
#include<iostream>
using namespace std;
//引用:给变量起别名
//语法:数据类型 &别名 = 原名;(数据类型得一样)
int main()
{int a = 10;int& b = a;cout << a << endl;cout << b << endl;b = 20;cout << a << endl;cout << b << endl;system("pause");return 0;
}
注意事项:
(1)引用必须初始化
(2)引用一旦初始化后,就不可以更改
引用作函数传递参数:
#include<iostream>
using namespace std;
void func(int& a, int& b)
{int num = a;a = b;b = num;
}
int main()
{int a = 0;int b = 10;func(a, b);//引用传递,形参会修饰实参cout << a << endl;cout << b << endl;system("pause");return 0;
}
引用做函数返回值:
#include<iostream>
using namespace std;
//引用作函数返回值
//1.不要返回局部变量的引用
int& test01()
{static int a = 10;//静态变量放在全局区return a;
}
int main()
{int &num = test01();cout << num << endl;cout << num << endl;test01() = 1000;//如果函数的返回值是引用,这个函数调用可以作为左值cout << num << endl;cout << num << endl;system("pause");return 0;
}
引用的本质:
引用的本质是一个指针常量
常量引用:
#include<iostream>
using namespace std;
//加上const之后,值不可改,避免出现错误
void showNum(const int& a)
{cout << a << endl;
}
int main()
{//常量引用//使用场景:用来修饰形参,防止误操作//加上const之后,编译器将代码修改 int temp = 10;const int & ref =temp;//const int& ref = 10;int a = 1000;showNum(a);system("pause");return 0;
}
函数默认参数:
#include<iostream>
using namespace std;//函数默认参数//int func(int a, int b, int c)可以这样写
//也可以下面这样写
//注意事项:
//如果在函数定义实现处写出默认值,就可以在main中省略后两个值的输入
//声明和实现处只能有一处默认值
//在函数内部不能再赋予其其他默认值
//语法: 返回值类型 函数名 (形参=默认值){}
int func(int a, int b=20, int c=30)
{return a + b + c;
}int main()
{cout << func(10, 20, 30) << endl;system("pause");return 0;
}
函数占位参数:
//函数占位参数
//返回值类型 函数名(数据类型,占位){}
//下面这个函数,使用int占在那里int还可以有默认值
void func(int a, int=10)
{cout << "this is func" << endl;}
int main()
{func(10, 10);system("pause");return 0;
}
函数重载:
//函数重载
//作用:函数名可以相同,提高复用性
//函数重载满足条件:1 同一个作用域下 2 函数名称相同 3 函数参数类型不同 或者 个数不同 或者顺序不同
//函数的返回值不可以当作函数重载的条件
void func(long int b,int a)
{cout << "func的调用" << endl;
}void func(int a)
{cout << "func" << endl;
}
void func(long int a)
{cout << "func" << endl;
}
void func(int a,long int b)
{cout << "func" << endl;
}
int main()
{func(10);system("pause");return 0;
}
函数重载注意事项:
//1.引用作为函数重载的条件
//下面这两个这样写是被允许的 const也算不同类型的一种
void func(int& a)
{}
void func(const int& a)
{}
int main()
{//这样会调用上面的函数int a = 10;func(a);//这样会调用下面的参数//直接传入10,上面的函数不合法,传入下面的函数含有const,编译器会开辟出int t =10 int &a=t来使其合法func(10);system("pause");return 0;
}
//2.函数重载遇到默认参数
void func(int a,int b=10)
{}
void func(int a)
{}
int main()
{func(10);//这样会出现歧义,无法重载return 0;
}
类和对象
c++面向对象的三个特性:封装 继承 多态 万事万物都可以作为对象,对象上有其属性和行为
设计一个圆类,来计算其周长
//创建全局变量
double pi = 3.14;
//class代表设计一个类,后面紧跟类的名称
class Circle
{//一个类需要具备的要素;访问权限,属性,行为//访问权限
public://属性int m_r;//行为//获取圆的周长double calculator(){return 2 * pi * m_r;}};
int main()
{//通过该类,创建具体的对象(实例化)Circle c1;//给圆对象进行属性的赋值c1.m_r = 10;//使用行为(函数)进行相应操作cout << "圆的周长为: " << c1.calculator() << endl;system("pause");return 0;
}
#include<string>;class Student
{
public://字符串使用string,同时引用相应头文件string S_name;//idint S_studentcard;void S_showname(){cout << "学生的名字是" <<S_name << endl;}void S_showcard(){cout << "学生的学号是" << S_studentcard << endl;}
};
int main()
{Student ZZM;//字符串使用双引号,单字符使用单引号ZZM.S_name = "张泽明";ZZM.S_studentcard = 2023;ZZM.S_showcard();ZZM.S_showname();system("pause");return 0;
}
设计类时,可以把属性和行为放在不同的权限下,加以控制
//三种访问权限:public(公共权限)protected(保护权限)private(私有权限)
//public 成员类内可以访问,类外也可以访问
//protected 类内可以访问 类外不可以访问
//private 类内可以访问 类外不可以访问
//后两个在继承里面体现出区别看,子类可以访问父类中的保护内容,不可以访问私有内容
class person
{
public:string M_name;
private:string M_passport;
protected:string M_ID;
public:void func(){//类内可以访问M_ID = "123456";M_name = "zhangsan";M_passport = "123123";}
};
int main()
{//实例化对象person p1;p1.M_name = "nima";// 这类内容是访问不到的// p1.M_ID = "goode";//函数也一样p1.func();system("pause");return 0;
}
在C++中class和struct默认的访问权限不同
struct默认权限是 public
class默认权限是 private
默认权限就是,不进行权限设置,属性和行为的访问权限
权限设置技巧
class Person
{
public://通过行为的设置进行信息的读取void setname(string name){string M_name = name;}string getname(){return M_name;}private://将属性放置在私有权限内string M_name;string M_car;string M_id;
};
函数传入一个实例的格式
bool func(cube& c)
{
}
构造函数和析构函数:
//构造函数和析构函数是为了完成对象的初始化和清理操作
//如果我们不提供,编译器会自动提供(空实现)
//对象的初始化和清理
class person
{//1.构造函数,对象的初始化操作//没有返回值 不用写void//函数名与类名相同//构造函数可以有参数,可以发生重载//创建对象时,构造函数会自动调用,且只调用一次person(){}//2.析构函数 进行清理操作//没有返回值,不写void//函数名与类名相同 在名称前加上~//析构函数不存在参数,不能发生重载//对象在销毁前 会自动调用析构函数,而且只会调用一次~person(){}//system("pause")就是在这一步停止的意思
};
构造函数的分类和调用
//构造函数:
//两种分类方式:
//按参数分为:有参构造和无参构造
//按类型分为:普通构造和拷贝构造
//三种调用方式:
//括号法 显示法 隐式转换法//分类
class person
{
public://构造函数person()//无参{}person(int a)//有参{}//拷贝构造函数person(const person &p){}//析构函数~person(){}
};
//构造函数的调用
int main()
{//1.括号法person p1;//无参person p2(10);//有参person p3(p2);//拷贝函数//注意事项,调用无参构造函数时,不要加()因为会被认为是一个函数声明//2.显示法person p4;person p5 = person(10);//有参person p6 = person(p5);//拷贝构造person(10);//匿名对象,执行此行之后,系统会立刻回收该对象//注意事项:不要利用拷贝构造函数初始化匿名对象,因为其相当于进行实例化//3.隐式转换法person p7 = 10;//相当于 person p7 = person(10);system("pause");return 0;
}
拷贝函数调用时机
//通常有三种调用情况
class person
{
public:int M_age;person(){cout << "无参构造函数调用" << endl;}person(int a){cout << "有参构造函数调用" << endl;}person(const person& p){cout << "拷贝构造函数调用" << endl;}~person(){cout << "析构函数调用" << endl;}
};
//1.使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{person p1 (20);person p2(p1);cout << p2.M_age << endl;
}
//2.值传递的方式给函数参数传值
void work(person p)
{}
void test02()
{person p;//这里调用一个拷贝函数,创建新的数据传入workwork(p);
}
//3值方式返回局部对象
person work2(person p)
{person p1;//调用拷贝函数,返回局部变量的值return p1;
}
构造函数的调用规则:
//默认情况下,编译器会给一个类添加三个函数
//1.默认构造函数(无参,函数体为空)
//2.默认析构函数(无参,函数体为空)
//3.默认拷贝构造函数,对属性进行值拷贝
//构造函数调用规则:
//如果用户定义有参构造函数,编译器不再提供默认无参构造函数,但是会提供默认拷贝函数(没有默认构造函数,调用报错)
//如果用户定义拷贝构造函数,编译器不会再提供其他构造函数(同理)
深拷贝与浅拷贝
//浅拷贝:简单的拷贝赋值操作
//深拷贝:在堆区重新申请空间,进行拷贝操作
class person
{
public:person(){cout << "无参构造函数调用" << endl;}person(int age, int height){m_age = age;int* m_height = new int(height);cout << "有参构造函数调用" << endl;}person(const person& p){m_age = p.m_age;//m_height = p.m_height;编译器实现这行代码的时候,会导致堆区数据被重复释放,所以要重新申请重新使用int m_height = new int(*p.m_height);}~person(){//析构代码,将堆区开辟数据做释放操作if (m_height!=NULL){delete m_height;m_height = NULL;}}int m_age;int* m_height;
};
初始化列表
//c++的初始化列表
class person
{
public:person(int a, int b, int c) :m_a(a), m_b(b), m_c(c){}int m_a;int m_b;int m_c;
};
类对象作为类成员
//类对象作为类成员
//构造函数:先调用成员的构造函数
//析构函数:先调用自身的析构函数
class phone
{
public:phone(string pname){p_name = pname;}string p_name;
};
class person
{
public://这里类似于隐式转换 phone p = p_name;person(string age, string p_name) :m_age(age), p(p_name){}int m_age;phone p;
};
静态成员:
class person
{
public://静态成员//所有成员使用一个数据//编译时就分配内存//类内声明,类外初始化static int m_A;//静态成员同样具有访问权限
private:static int m_b;
};
//类外初始化 person:: 代表person下的成员
int person::m_A = 10;
int person::m_b = 20;
void test01()
{//静态成员的两种访问方式//通过对象进行访问person p;cout << p.m_A << endl;//通过类进行访问cout << person::m_A << endl;
}
静态函数
//静态函数
//所有对象共享一个函数
//静态函数只能访问静态成员变量
class person
{//静态函数同样存在权限访问问题
public:static void func(){m_a = 20;//m_b = 20;不能访问该变量}static int m_a;int m_b;
};
int person::m_a = 10;
void func()
{//两种访问方式person p;p.func();//类名访问person::func();
}
成员变量和成员函数分开存储:
class person
{//空对象大小是1//c++编译器会给每个空对象分配一个字节空间,为了区分空对象占内存的位置//非静态成员变量属于类上int m_a;//静态成员变量不属于类上static int m_b;//非静态成员函数不属于类上void func(){}//静态成员函数不属于类上static void func(){}
};
int person::m_b = 10;
void test01()
{person p;cout << sizeof(p) << endl;
}int main()
{test01();system("pause");return 0;
}
this指针:
//this指针的作用(每个非静态成员函数都有,不用定义直接调用)
//1.解决名称冲突,当形参和变量名称一样时
class person
{
public:person(int age){//this指向的是被调用成员函数所属的对象,就是创建的person pthis->age = age;}//这里使用person的引用才能对创建的对象进行数据修改,不然就是简单的数据拷贝不能叠加person& addage(person p){this->age += p.age;//返回对象本身使用*thisreturn *this;}int age;
};
//2.返回对象本身用*this
void test01()
{person p1(10);person p2(10);//链式编程思想p1.addage(p2).addage(p2).addage(p2);}
空指针访问成员函数:
class person
{
public:void func(){//一般这里会隐形地给出this->m_age,因此使用空指针指向这个函数就会出现问题//使用if判断一下,为空就直接returncout << m_age << endl;}int m_age=18;
};
void test01()
{person *p=NULL;p->func();
}
int main()
{test01();return 0;
}
常函数:
class person
{//const本质上是修饰的this指针常量,使得指针常量指向的值也不能修改void func()const{this->m_a = 10;this->m_b = 10;}int m_a;mutable int m_b;//被mutable修饰的量可以在常函数中进行修改
};
常对象:
void test01()
{//常对象不能修改成员属性//mutable修饰的可以修改const person p1;//常对象不能调用普通成员函数,能调用常函数
}
全局函数作友元:
//友元使对象可以访问private的属性数据
class Building
{//friend 放在函数前面friend void test01(Building* B);
public:string livingroom;
private:string bedroom;
public:Building(){livingroom = "kt";bedroom = "ws";}};
void test01(Building *B)
{cout << B->livingroom << endl;cout << B->bedroom << endl;
}
类作友元:
class Building
{friend class goodgay;
public://在类外写函数,类内的函数就不能有函数体包括大括号{}Building() ;string livingroom;
private:string bedroom;
};
class goodgay
{
public:goodgay() ;void visit() ;
private:Building* building;
};
Building::Building()
{livingroom = "keting";bedroom = "woshi";
}
goodgay::goodgay()
{building = new Building;
}
//注意类外写函数的格式
void goodgay::visit()
{cout << building->bedroom<<endl;cout << building->livingroom<<endl;
}
void test01()
{goodgay g1;g1.visit();
}
int main()
{test01();system("pause");return 0;
}
成员函数作友元:
friend goodgay::visit();
运算符重载的格式实际上就是函数的格式再稍微改变一下
加号运算符重载:
//运算符重载:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
//运算符重载也能发生函数重载
//1.成员函数作运算符重载
class person
{
public:person(int a, int b){m_A = a;m_B = b;}person operator+(person& p){this->m_A += p.m_A;this->m_B += p.m_B;return *this;}int m_A ;int m_B ;
};
//2.全局函数作运算符重载
person operator+(person& p1, person& p2)
{person temp(0,0);temp.m_A = p1.m_A + p2.m_A;temp.m_B = p1.m_B + p2.m_B;
}
void test01()
{person p1(10, 10);person p2(10, 10);person p3(0, 0);p3 = p1 + p2;cout << p3.m_A << endl << p3.m_B<<endl;}
int main()
{test01();system("pause");return 0;
}
移位运算符重载:
//cout是ostream类的一个对象
//不能使用成员函数进行移位运算符重载,因为产生不了相应的效果
class person
{
public:friend ostream& operator<<(ostream& cout, person& p);person(int a,int b){m_a = a;m_b = b;}
private:int m_a;int m_b;
};
//返回值为ostream&,符合链式编程思想
ostream& operator<<(ostream& cout, person& p)
{cout << p.m_a << p.m_b;return cout;
}
void test01()
{person p1(10, 10);cout << p1 << endl;
}
递增运算符重载:
//成员函数实现递增运算符重载
class intage
{friend ostream& operator<<(ostream& cout, intage i);
public:intage(int a){m_num = a;}//前置递增//必须使用intage&,不然就会出问题intage& operator++(){m_num++;return*this;}//占位参数实现后置递增,加上一个int代表后置递增//这里必须使用intage,因为返回的temp是局部变量,会被释放掉,不过还是会出问题intage operator++(int){int temp = m_num;m_num++;return temp;}private:int m_num;
};
//全局函数实现<<重载
ostream& operator<<(ostream&cout,intage i)
{cout << i.m_num;return cout;
}
void test01()
{intage in = 10;cout << ++(++in) << endl;cout << in << endl;cout << (in++)++<< endl;cout << in<< endl;
}
int main()
{test01();system("pause");return 0;
}
赋值运算符重载:
//c++编译器会给一个类添加一共四个函数
//默认构造函数,默认析构函数,默认拷贝构造函数
//赋值运算符 operator=,对属性进行值拷贝
//可以解决浅拷贝导致的指针重复释放的问题
关系运算符重载(大于 小于 不等于 等于==)
跟前几个差不多
函数调用运算符重载,就是()
在类中重载的(),被称为仿函数,也跟上面的差不多
继承:
利用继承,可以减少重复代码
//继承语法:class 子类:继承方式 父类
class base
{
public:void b(){cout << 123 << endl;}
};
class child :public base
{};
继承方式:
子类的对象模型:
class base
{
public:int m_a;//private仍然被继承下来,但是被隐藏,没法调用
private:int m_b;
protected:int m_c;};
class son :public base
{
public:int m_d;
};
void test01()
{//结果是16,子类会继承父类中的所有数据cout << sizeof(son) << endl;
}
int main()
{test01();system("pause");return 0;
}
构造和析构的顺序:
先构造父类,再构造子类,析构相反
继承中,同名成员处理方式
class base
{
public:void func() {};void func(int a) {cout << a << endl;};int m_a;
};
class son :public base
{
public:void func() {};int m_a;
};
void test01()
{son s;//调用子类,直接调用s.m_a;s.func();//调用父类,就加作用域即可s.base::func(100);s.base::m_a;
}
int main()
{test01();system("pause");return 0;
}
同名静态成员的处理方式:
//同名静态成员属性
class base
{
public:static int m_a;
};
int base::m_a = 100;
class son :public base
{
public:static int m_a;
};
int son::m_a = 50;
void test01()
{//1.通过作用域访问//2.通过类名进行访问cout << son::m_a << endl;cout << son::base::m_a << endl;//静态成员函数也一样
}
继承的语法:
//多继承
class son :public base1, public base2
{};
菱形继承:
两个类同时继承自一个类,再同时继承给一个子类,那么该子类对于第一个类的数据继承了两份
class animal
{
public:int m_a;
};
//利用虚继承解决菱形继承问题
//虚继承,继承一个指针列表,指向该数据(大概)
class sleep:virtual public animal{};
class tuo:virtual public animal{};
class sleeptuo:public sleep,public tuo{};
void test01()
{sleeptuo st;//不会报错st.m_a;
}
多态:
//静态多态:函数重载 运算符重载属于静态多态
//动态多态:派生类和虚函数实现运行时多态
//二者区别:
//静态多态:函数地址早绑定 编译阶段确定函数地址
//动态多态:函数地址晚绑定 运行阶段确定函数地址
//多态满足条件:1.有继承关系2.子类重写父类中的虚函数
//多态使用条件:父类指针或引用指向子类对象
class animal
{public://添加virtual使地址晚绑定,传入参数之后再绑定,使speak处于多种状态virtual void speak(){cout << 1;}
};
class cut :public animal
{
public:void speak(){cout << 2;}
};
class dog :public animal
{
public:void speak(){cout << 3;}
};
void dospeak( animal& animal)
{animal.speak();
}
void test()
{cut c;dospeak(c);dog d;dospeak(d);
}
int main()
{test();system("pause");return 0;
}
多态实现计算机类
#include<iostream>
using namespace std;
#include<string>
//利用多态实现计算机类
// 开闭原则:多扩展进行开放,对修改进行关闭
//多态的好处:
//1.组织更加清晰
//2.可读性强
//3.利于前期和后期的维护
//创建一个计算机的抽象类
class AbstrateCalcultor
{
public:virtual int getResult(){return 0;}int Num1=0;int Num2=0;
};
//加法类
class AddCalcultor :public AbstrateCalcultor
{int getResult(){return Num1 + Num2;}
};
//减法类
class SubCalcultor :public AbstrateCalcultor
{int getResult(){return Num1 - Num2;}
};
//乘法类
class MutiCalcultor :public AbstrateCalcultor
{int getResult(){return Num1 * Num2;}
};
void test01()
{AbstrateCalcultor* abs = new AddCalcultor;abs->Num1 = 1;abs->Num2 = 2;cout << abs->Num1 << "+" << abs->Num2 << "=" << abs->getResult() << endl;
}
int main()
{test01();system("pause");return 0;
}
纯虚函数和抽象类
class base
{
public://类中只要有一个纯虚函数,就被称为抽象类//纯虚函数virtual void func() = 0;//抽象类的特点://1.无法实例化对象//2.子类必须重写父类中的纯虚函数,否则也无法实例化对象
};
class son :public base
{
public:virtual void func(){cout << "abs" << endl;}
};
虚析构和纯虚析构
//虚析构和纯虚析构
//为了解决父类指针释放子类对象的问题
//子类出现开辟数据然后释放的操作时需要
//存在纯虚析构函数的类也称为抽象类
class Animal
{
public:virtual void speak() = 0;Animal(){cout << 1 << endl;}//虚析构virtual ~Animal(){cout << 2 << endl;}//纯虚析构,需要在外面实现一下virtual ~Animal() = 0;
};
Animal::~Animal()
{}
class Cat :public Animal
{
public:virtual void speak(){cout << *Name << "在说话" << endl;}Cat(string C_Name){Name = new string(C_Name);cout << 3 << endl;}~Cat(){cout << 4 << endl;if (Name != NULL){delete Name;Name = NULL;}}string* Name;
};
void test01()
{Animal* an = new Cat("name");an->speak();//delete的是父类指针,无法进入子类虚构代码,因此使用虚析构delete an;
}
int main()
{test01();system("pause");return 0;
}
//析构函数的调用时机:创建实例向其中传值或者其他实例的时候
//析构函数的调用时机:销毁实例或者数据的时候
文件操作
//程序运行时产生的数据属于临时数据,运行结束就会被释放掉,通过文件可以将数据永久化
//使用文件要包含头文件文件流<fstream>
//文件类型:
//1,文本文件:以文本的ASCII形式存储
//2,二进制文件:文本以二进制形式存储,一般不能直接读取
//操作文件的三大类:
//1.ofstream 写操作
//2.ifstream 读操作
//3.fstream 读写操作
写文件:
//1.包含头文件
#include<fstream>
//2.创建流对象(写操作)
ofstream ofs;
void test()
{//3.打开文件ofs.open("666.txt", ios::out);//4.写文件ofs << "123" << endl;ofs << "456" << endl;ofs << "789" << endl;//5.关闭文件ofs.close();
}
int main()
{test();system("pause");return 0;
}
读文件:
#include<fstream>
//读文件
ifstream ifs;
void test()
{ifs.open("666.txt", ios::in);//判断是否读取成功if (!ifs.is_open()){cout << "读取失败" << endl;}//三种读取数据的方式// 一行一行地读的//char buf[1024] = { 0 };while (ifs >> buf){cout << buf << endl;cout << 1;}//char buf[1024] = { 0 };while (ifs.getline(buf, sizeof(buf))){cout << buf << endl;cout << 1;}//string buf;while (getline(ifs, buf)){cout << buf << endl;}//关闭文件ifs.close();
}
int main()
{test();system("pause");return 0;
}
二进制文件:
写文件
#include<fstream>
class Person
{
public:char Name[64];int Age;
};
//创建流对象和打开文件可以写在同一个地方
ofstream ofs("write.txt", ios::out | ios::binary);
void test()
{Person p = { "张三",18};//写文件ofs.write((const char*)&p,sizeof(&p));ofs.close();}
int main()
{test();return 0;
}
读文件
#include<fstream>
class Person
{
public:char Name[64];int Age;
};
ifstream ifs;
void test()
{Person p;ifs.open("write.txt", ios::in | ios::binary);//判断是否读取成功if (!ifs.is_open()){}ifs.read(( char*) & p, sizeof(Person));cout <<p.Name << endl << p.Age << endl;
}
int main()
{test();system("pause");return 0;
}