C++笔记

c++学习

分文件编写

1.创建.h后缀名的头文件

2.创建.cpp后缀名的源文件

3.在.h里声明函数

4.在.cpp里编写函数

指针

int main() {
	int a;
	cin >> a;
	int *p = &a;
	cout << a << ' ' << *p << ' ' << p << endl;
	*p = 2023;
	cout << a << ' ' << *p << ' ' << p;
	return 0;
}

通过*p直接改变a的数值,p为a的地址,不发生改变

指针的数据类型占用4个字节(32位) 8个(64位)

空指针

int *p = NULL;
空指针 >> 不可访问

野指针

int *p = (int *)0x1100;
野指针 >> 指向非法空间

利用指针访问数组

int arr[3] = { 0, 1, 2 };
	int* p = arr;
	for (int i = 0; i < 3; i++) 	{
		cout << *p << endl;
		cout << p << endl;
		p++;
	}

指针和函数

值传递无法改变实参
地址传递可以改变实参
例
#include<iostream>
using namespace std;

void swap(int* p1, int* p2) {

	int t = *p1;
	*p1 = *p2;
	*p2 = t;
}
int main() {
	int a = 10;
	int b = 20;

	swap(&a, &b);

	cout << a << ' ' << b;
	return 0;
}

const

常量指针 >>> 指针的指向可以修改,但指针的值不可以改

const int *p = &a;
*p = 20; 错误
p = &b; 正确

指针常量 >>> 指针的指向不可以改,指针指向的值可以改

int * const p = &a;
*p = 20; 正确
p = &b; 错误

同时被修饰 >>> 指针的指向和指向的值都不可以改

const int * const p = &a;
*p = 20; 错误
p = &b; 错误

结构体

struct Student {
	string name;
	int age;
	float score;
}s3;

int main() {
//创建变量时,struct可以省略
	//创建方式1
	struct Student s1;
	s1.name = "yzb";
	s1.age = 19;
	s1.score = 100;
	//创建方式2
	struct Student s2 = { "YZB",19,100 };
	//创建方式3
	//创建结构体时同时创建结构体变量
	s3.name = "YYY";
	s3.age = 20;
	s3.score = 80;
	return 0;
}

结构体数组

struct Student {
	string name;
	int age;
	float score;
};
int main() {
	Student  stuArray[3] =
	{
		{"张三",18,100},
		{"李四",19,99},
		{"马武",20,92}
	};
	for (int i = 0; i < 3; i++) {
		cout << stuArray[i].name << ...
	}
	return 0;
}

结构体指针

int main() {
	Student s1 = { "yzb",19,100 };
	Student* p = &s1;
	cout << p->name;
	return 0;
}

结构体嵌套

struct student {
	string name1;
	string name2;
	string name3;
};

struct teachar {
	string name;
	int id;
	int age;
	student name0;
};

int main() {
	teachar t1 = { "MALI",001,29,"王虎","马六","小李" };
	cout << t1.name0.name1;
	return 0;
}

结构体const使用

无法改变结构体的内容,防止误操作

void PrintStudent(const Student* s) {
	s->age = 18;
	cout << s->age;
};

int main() {
	Student s = { "李四",001,99 };
	PrintStudent(&s);
	return 0;
} 

代码四区

代码区:存放函数体的二进制代码,由操作系统进行管理的。

代码区存放CPU执行的机器指令既程序汇编而成的二进制代码。
代码区是共享的,对于频繁执行的程序,内存中只需要保存一份即可。
代码区是只读的,只读的原因是防止程序意外修改了指令。

全局区:存放全局变量和静态变量以及常量

局部变量和局部常量所在地址和其他变量相距很远,不在全局区之中。

栈区:由编译器自动分配释放,存放函数的参数值,局部变量等。
不要返回局部变量的地址,栈区开辟的地址由编译器自动释放。

堆区:由程序员分配和释放,若程序员不释放,程序结束后由操作系统回收。

主要利用new关键字开辟堆区

int* func()
{
	int* a = new int(10);
	return a;
}
int main(void) {
	int* p;
	p = func();
	cout << *p << endl;
	return 0;
}

利用new关键字,将数据开辟在堆区,指针本质也是局部变量,放在栈上,但指针保存的数据放在堆区

new的使用和释放

int* func() {
	int* p = new int(100);//在堆区创建整型数据,new返回是该数据类型的指针
	return p;
}

void test(){
	int* p = func();
	cout << *p << endl;//堆区数据由程序员直接释放
	delete p;//释放数据
	cout << *p << endl;//无法输出
}
int main() {
	test();
	return 0;
}
int *arr = new int [10] //开辟大小为10的数组
返回的为首地址 通过首地址继续修改范围
delete [] arr; //释放数组 

引用

int a = 10;
创建引用
int& b = a;

注意: 1.创建必须初始化

​ 2.引用一旦初始化无法改变;

引用传递

使形参修饰实参

void swapab(int &a, int &b) {
	int temp = a;
	a = b;
	b = temp;
}
int main() {
	int a = 10; 
	int b = 20;
	swapab(a, b);
	cout << a << b;
} 

引用做函数的返回值

//引用做函数的返回值 >> 不要返回局部变量的引用
int& test1() {
	int a = 10;
	return a;
}
int& test2() {
	static int a = 10;//静态变量,在全局区
	return a;
}
//函数的调用可以作为左值,继续赋值操作
int main() {
	int& b = test2();
	cout << b << endl;
} 

引用的本质为指针常量 int* const ref = &a; >>> int &ref = a

常量引用

主要用于修饰形参,防止误操作

void test(const int &a)//加const ,a的数值无法改变,防止误操作
int main() {
	int a = 10;
	int& ref = 10;//引用必须引用合法内存空间
	const int& ref = 10;//加上const代码修改为了 int temp = 10; const int & ref = temp;
	ref = 20; //无法修该,变成只读
} 

函数高级

函数默认参数

int add(int a, int b = 20, int c = 30){
	return a + b + c;
}

如果某个位置有了默认参数,这个位置往后都得有默认值;

声明中有默认参数则函数实现中不能有,只能有一部分有;

函数占位参数

void fun(int a, int){
 ....
}

函数重载

函数名相同,提高复用性

条件 1.同一个作用域

​ 2.函数名称相同

​ 3.函数参数类型不同或者个数不同或者

​ 4.仅返回类型不同的不可以作为重载条件

引用作为重载条件

void test1(int& a) {
	...
}

void test1(const int& a) {
...
}

int main() {
	int a = 10;
	test1(a);调用上面的
	test1(10);调用下面的
} 

函数重载碰到默认参数

void test1(int a) {
	...
}

void test1(int a, int = 20) {
...
}

int main() {
	int a = 10;
	test1(a);//编译器无法判断,出现歧义
} 

类和对象

面向对象的三大特性 封装 继承 多态

封装

意义:1.将属性和行为作为一个整体,表现生活中的事物

语法

class 类名{访问权限:属性/行为};
const double P = 3.14;
class Circle
{
public:
	int mr;
	double calculateZC() {
		return 2 * P * mr;
	}
	void mrr(int a){
	mr = a;
	}
};
int main() {
	Circle c1;//实例化
	c1.mr = 10; // 或者 c1.mrr(10);
	cout << c1.calculateZC();
}

类中属性和行为统一称为成员

属性 >> 成员属性 成员变量

行为 >> 成员函数 成员方法

意义:2.将属性和行为放在不同权限下,加以控制

权限

class默认权限为私有

public公共权限 成员类内可以访问,类外可以访问;

protected保护权限 成员类内可以访问,类外不可以访问;子类可以访问父类;

private私有权限 成员类内可以访问,类外不可以访问;子类不可以访问父类;

class和struct区别va

默认访问权限不同 struct默认权限为公有,class默认权限为私有

成员属性设置为私有

1.将所有成员属性设置为私有,可以自己控制读写权限

2.对于写权限,我们可以检测数据的有效性

对象特性

对象的初始化和清理

构造函数语法 类名(){}

可以有参数,可以发生重载 会自动调用,只调用一次

按参数分为: 有参构造和无参构造

按类型分为: 普通构造和拷贝构造

Person(const  Person &p)//拷贝构造函数
	{
		age = p.age;
		cout << "拷贝构造函数的调用" << endl;
		cout << "年龄:" << age << endl;
    }

调用方式

1.括号法
Person p1;调用默认构造函数使,不加()
Person p2(10);
Person p3(p2);

2.显示法
Person p1;
Person p2 = Person(10);
Person p3 = Person(p2);

Person(10);匿名对象 当前行执行完系统会立即回收匿名对象
不要利用拷贝构造函数,初始化匿名对象

3.隐式转化法
Person p4 = 10;
Person p5 = p4  ;

拷贝构造函数的调用时机

1.使用一个已经创建完毕的对象来初始化一个新对象

2.值传递的方式给函数参数传值

3.以值方式返回局部对象

构造函数的调用规则

默认情况 一个类会添加3个函数

1.默认构造函数 2.默认析构函数 3.默认拷贝构造函数

规则 用户定义有参构造函数,则c++不提供无参构造,但会提供默认拷贝函数

如果用户定义拷贝构造函数,c++不提供其他构造函数

深拷贝和浅拷贝

浅拷贝:简单的赋值拷贝操作

深拷贝:在堆区重新申请空间,进行拷贝操作

初始化列表

语法:构造函数():属性1(值1),属性2(值2)....{}

class Person
{
public:
	 //初始化列表
	Person(int a, int b, int c) :m_a(a), m_b(b), m_c(c)  {};
public:
	int m_a, m_b, m_c;
};
void main()
{
	Person p(2, 3, 4);
	cout << "a=" << p.m_a << endl;
	cout << "b=" << p.m_b << endl;
	cout << "c=" << p.m_c << endl;
}

静态成员

成员变量前加 static

1、 所有对象共享同一份数据
2、 在编译阶段分配内存
3、 类内声明,类外初始化

class person{
	static int m_A;
};
int person::m_A = 0;

静态成员函数

1、 所有对象共享同一个函数
2、静态成员函数只能访问静态成员变量
3、静态成员函数也有访问权限,写在private 里,类外是访问不到的

析构函数语法 ~类名(){}

不可以有参数,不可以发生重载 会自动调用,只调用一次

构造和析构都必须有,我们不提供,编译器会有一个空实现

c++对象模型和this指针

类内成员变量和成员函数分开储存,只有非静态成员变量才属于类的对象上

空对象占用内存空间为 1 ,每个空对象都有独一无二的内存地址

只有非静态成员变量属于类的对象上;

this指针

每一个非静态成员函数只会诞生一份函数实例,多个同类型的对象会共用一块代码

1.this指针不需要定义,直接使用即可
2.当形参和成员变量同名时,可用this指针来区分

Person(int age)
	{
		this->age = age;
	}

3.在类的非静态成员函数中返回对象本身,可使用return *this
4.注意空指针访问的问题

const修饰成员函数

  1. 成员函数后加const后我们称为这个函数为常函数
  2. 常函数内不可以修改成员属性
  3. 成员属性声明时加关键字mutable后,在常函数中依然可以修改
  4. 声明对象前加const称该对象为常对象
  5. 常对象只能调用常函数
  6. 常对象可以修改静态变量的值

友元

全局函数做友元

friend void goodgay(Building * building);

类做友元

friend class goodgay;

成员函数做友元

friend void goodgay::vist1();//注意要写上作用域,不能只写函数;

运算符重载

operator 加需要重载的符号

+重载

#include<iostream>
using namespace std;

class P {
public:
	int a;
	int b;
	/*P operator+(P& p) {
		P temp;
		temp.a = this->a + p.a;
		temp.b = this->b + p.b;
		return temp;
	}成员函数重载加号*/
};

P operator+(P &p1,P &p2) {
	P temp;
	temp.a = p1.a + p2.a;
	temp.b = p1.b + p2.b;
	return temp;
}//全局函数重载加号

int main() {
	P p1;
	p1.a = 1;
	p1.b = 3;
	P p2;
	p2.a = 1;
	p2.b = 3;
	P p3 = p1 + p2;
	cout << p3.a << ' ' << p3.b;
}

调用本质

Person p3 = p1.operator+(p2);
Person p3 = operator+(p1,p2);

<<重载

#include<iostream>
using namespace std;

class P {
public:
	int a;
	int b;
};

ostream& operator << (ostream& cout, P& p1) {
	cout << p1.a << ' ' << p1.b;
	return cont;
}

void test() {
	P p1;
	p1.a = 1;
	p1.b = 3;
	cout << p1 << endl;
}
int main() {
	test();
}

++重载

#include<iostream>
using namespace std;

class P {
public:
    int a;
    //前置递增
    P& operator ++() {
        this->a++;
        return *this;
    }
    //后置递增
    P operator++(int) {
        P temp = *this;
        a++;
        return temp;
    }
};

ostream& operator<<(ostream& os, const P& p1) {
    os << p1.a;
    return os;
}

int main() {
    P p1;
    p1.a = 6;
    cout << p1++ << endl; //输出p1原始值6
    cout << p1 << endl; //输出递增后的p1值7
    return 0;
}

= 重载

#include<iostream>
using namespace std;

class P {
public:
    int a;
    P(int a) :a(a) {};
    P& operator=(const P& p) {
        /*if (a != NULL) {
            delete a;
            a = NULL;
        }数据是否在堆区,在则释放*/
        a = p.a;
        return *this;
    }
};
int main() {
    P a(10);
    P b(20);
    P c(30);
    a = b = c;
    cout << a.a << ' '<< b.a << ' ' << c.a;
}

关系运算符重载

== 重载(举例)

#include<iostream>
using namespace std;

class P {
public:
    int a;
    P(int a) :a(a) {};
};

bool operator==(const P& p1, const P& p2) {
    if (p1.a == p2.a) {
        return true;
    }
    else return false;
}

int main() {
    P a(10);
    P b(20);
    if (a == b) {
        cout << "相等";
    }
    else cout << "不等";
}

() 重载 >>> 仿函数

无固定写法,很灵活,自己玩去

继承

减少重复代码

class 子类 :继承方式	父类

子类也叫做派生类 父类也叫做基类

继承方式 :公共继承 保护继承 私有继承

父类中所有非静态成员属性都会被子类继承下去,私有成员属性被编译器隐藏了,因此访问不到,但依旧被继承了

查看对象模型

开发人员命令提示工具 跳转盘符 C: cd 路径 cl /d1 reportleSingClassLayout 类名 文件名

继承中先调用父类构造函数,在调用子类构造函数析构函数,析构顺序与构造相反

同名处理方式 >> 加作用域

同名成员属性
Son s;
cout << s.a << s.Base::a << endl;
同名成员函数
Son.s;
s.func();
s.Base::func();

如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数

想访问到被隐藏的函数,加作用域即可

对于同名静态成员

1.对象访问
Son s;
cout << s.a << s.Base::a << endl;
2.类名访问
Son s;
cout << Son::a << Son::Base::a << endl;

多继承语法

class 子类 : 继承方式 父类1 ,继承方式 父类2

菱形继承

出现相同数据时 加作用域可以进行访问 但两份数据 会导致资源浪费

需要使用虚继承的方式解决这个问题 继承前加 virtual 变为虚继承 vbptr 虚基类指针

#include<iostream>
using namespace std;

class A{
public:
    int age;
};

class B:virtual public A {};
class C:virtual public A {};
class D :public B, public C {};
int main()
{
    D test;
    test.age = 18;
    cout << test.age << endl;
    test.D::age = 19;
    cout << test.age << endl;
    test.C::age = 20;
    cout << test.age << endl;
}

多态

多态分为两类
静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名
动态多态: 派生类和虚函数实现运行时多态

静态多态和动态多态区别
静态多态的函数地址早绑定 - 编译阶段确定函数地址
动态多态的函数地址晚绑定 - 运行阶段确定函数地址

#include<iostream>
using namespace std;


class Animal{
public:
    virtual void speak(){ //函数前面加上virtual关键字,变成虚函数,编译阶段无法绑定他的地址
            cout << "动物在说话" << endl;
        }
    };

class Cat : public Animal{
    public:
        void speak(){
            cout << "喵喵" << endl;
        }
    };

class Dog :public Animal
{
public:

    void speak()
    {
        cout << "汪汪" << endl;
    }

};
//地址早绑定 在编译阶段确定函数地址
//这里可以这样理解:比如你是开餐馆的,早绑定就是一个老顾客(假设他来这只吃面条)来吃饭,你一看是这个老顾客就直接上面条(编译阶段直接按父类的走)。
//而晚绑定是新顾客,虽然来了但无法直接判断他吃,还得新顾客说自己吃什么才能上什么(看实际传入的子类是什么)

void dospeak(Animal &animal){
        animal.speak();
    }
    void test01(){
        Cat cat;
        dospeak(cat);

        Dog dog;
        dospeak(dog);
    }
int main(){
    test01();
    system("pause");
}

多态满足条件:
1、有继承关系
2、子类重写父类中的虚函数
重写:函数返回值类型 函数名 参数列表 完全一致称为重写
多态使用:
父类指针或引用指向子类对象

纯虚函数和抽象类

纯虚函数语法 virtual 返回值类型 函数名 (参数列表) = 0;

当类中有纯虚函数则这个类称为抽象类

抽象类特点: 无法实例化对象

子类必须重写抽象类中的纯虚函数,否则也属于抽象类

案例

//抽象制作饮品
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 {
public:
	//烧水
	virtual void Boil() {
		cout << "煮农夫山泉!" << endl;
	}
	//冲泡
	virtual void Brew() {
		cout << "冲泡咖啡!" << endl;
	}
	//倒入杯中
	virtual void PourInCup() {
		cout << "将咖啡倒入杯中!" << endl;
	}
	//加入辅料
	virtual void PutSomething() {
		cout << "加入牛奶!" << endl;
	}
};

//制作茶水
class Tea : public AbstractDrinking {
public:
	//烧水
	virtual void Boil() {
		cout << "煮自来水!" << endl;
	}
	//冲泡
	virtual void Brew() {
		cout << "冲泡茶叶!" << endl;
	}
	//倒入杯中
	virtual void PourInCup() {
		cout << "将茶水倒入杯中!" << endl;
	}
	//加入辅料
	virtual void PutSomething() {
		cout << "加入枸杞!" << endl;
	}
};

void DoWork(AbstractDrinking* drink) {
	drink->MakeDrink();
	delete drink;
}

void test01() {
	DoWork(new Coffee);
	DoWork(new Tea);
}

int main() {
	test01();
	system("pause");
	return 0;
}

虚析构和纯虚析构

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码

解决方式:将父类中的析构函数改为虚析构或者纯虚析构

虚析构和纯虚析构共性:

可以解决父类指针释放子类对象
都需要有具体的函数实现
虚析构和纯虚析构区别:

如果是纯虚析构,该类属于抽象类,无法实例化对象
虚析构语法:

virtual ~类名(){}

纯虚析构语法:

virtual ~类名() = 0;
类名::~类名(){}

总结:

  1. 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象

  2. 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构

  3. 拥有纯虚析构函数的类也属于抽象类

多态案例

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;

class CPU {
public:
    virtual void calculat() = 0;
};

class VoiCard{
public:
    virtual void display() = 0;
};

class Memory{
public:
    virtual void storage() = 0;
};

class Computer{
public:
    Computer(CPU * cpu,VoiCard * vc,Memory * mem){
        m_cpu = cpu;
        m_vc = vc;
        m_mem = mem;
    }

    void Work (){
        m_cpu ->calculat();
        m_vc ->display();
        m_mem ->storage();
    }

    ~Computer(){
        if(m_cpu != NULL){
            delete m_cpu;
            m_cpu = NULL;
        }
        if(m_vc != NULL){
            delete m_vc;
            m_vc = NULL;
        }if(m_mem != NULL){
            delete m_mem;
            m_mem = NULL;
        }
    }
private:
    CPU * m_cpu;
    VoiCard * m_vc;
    Memory * m_mem;
};
class Icpu : public CPU{
    virtual void calculat() {
        cout << "英特尔cpu开始工作" << endl;
    }
};
class Ivc : public VoiCard{
    virtual void display() {
        cout << "英特尔显卡开始显示" << endl;
    }
};
class Imem : public Memory{
    virtual void storage() {
        cout << "英特尔内存开始储存" << endl;
    }
};
class Lcpu : public CPU{
    virtual void calculat() {
        cout << "联想cpu开始工作" << endl;
    }
};
class Lvc : public VoiCard{
    virtual void display() {
        cout << "联想显卡开始显示" << endl;
    }
};
class Lmem : public Memory{
    virtual void storage() {
        cout << "联想内存开始储存" << endl;
    }
};
int main(){
    CPU * C = new Icpu;
    VoiCard * V = new Ivc;
    Memory *  M = new Imem;

    cout << "第一台电脑开始工作" << endl;
    Computer * CP = new Computer(C,V,M);
    CP -> Work();
    delete CP;

    cout << "-------------------" << endl;
    cout << "第二台电脑开始工作" << endl;
    Computer * CP2 = new Computer(new Lcpu,new Lvc,new Lmem);
    CP2 -> Work();
    delete CP2;
}

文本操作

操作时加文件流头文件

#include<fstream>

文件类型分 文本文件和二进制文件

操作文件三大类 ofstream:写文件 ifstream:读文件 fstream:读写文件

写文件操作流程

1.包含头文件

#include<fstream>

2.创建流对象

ofstream ofs;

3.打开文件

ofs.open("文件类型",ios::out);

4.写数据

ofs << "写入的数据";

5.关闭文件

ofs.close();
打开方式解释
ios::in为读文件而打开文件
ios::out为写文件而打开文件
ios::ate初始位置:文件尾
ios::app追加方式写文件
ios::trunc如果文件存在先删除,再创建
ios::binary二进制方式

注意: 文件打开方式可以配合使用,利用 | 操作符

例如: 用二进制方式写文件

ios::binary | ios::out

读文件流程

1.包含头文件

#include<fstream>

2.创建流对象

ifstream ifs;

3.打开文件并判断是否打开

ifs.open("文件类型",ios::in);
if(!ifs.is_open()){
cout << "打开失败" << endl;
return;
}

4.读数据

四种方式举例

#include<iostream>
#include<cstring>
#include<cmath>
#include<fstream>
using namespace std;

void test01(){
    ifstream ifs;
    ifs.open("test.txt",ios::out);
    if(!ifs.is_open()){
        cout << "文件打开失败" << endl;
        return;
    }
    //第一种方式
    //char a[1024] = { 0 };
    //while (ifs >> a)
    //{
    //	cout << a << endl;
    //}

    //第二种
    //char a[1024] = { 0 };
    //while (ifs.getline(a,sizeof(a)))
    //{
    //	cout << a << endl;
    //}

    //第三种
    string a;
    while (getline(ifs, a))
    {
    	cout << a << endl;
    }

    //第四种
    /*char a;
    while ((a = ifs.get()) != EOF)
    {
        cout << a;
    }*/
   ifs.close();
}

int main(){
    test01();
}

5.关闭文件

ifs.close();

二进制文件操作

以二进制的方式对文件进行读写操作

打开方式要指定为 ios::binary

写文件
二进制方式写文件主要利用流对象调用成员函数write

函数原型 :
ostream& write(const char * buffer,int len);

参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数

#include <fstream>
#include <string>

class Person
{
public:
	char m_Name[64];
	int m_Age;
};

//二进制文件  写文件
void test01()
{
	//1、包含头文件

	//2、创建输出流对象
	ofstream ofs("person.txt", ios::out | ios::binary);
	
	//3、打开文件
	//ofs.open("person.txt", ios::out | ios::binary);

	Person p = {"张三"  , 18};

	//4、写文件
	ofs.write((const char *)&p, sizeof(p));

	//5、关闭文件
	ofs.close();
}

int main() {

	test01();

	system("pause");

	return 0;
}

读文件

二进制方式读文件主要利用流对象调用成员函数read

函数原型:
istream& read(char *buffer,int len);

参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数

#include <fstream>
#include <string>

class Person
{
public:
	char m_Name[64];
	int m_Age;
};

void test01()
{
	ifstream ifs("person.txt", ios::in | ios::binary);
	if (!ifs.is_open())
	{
		cout << "文件打开失败" << endl;
	}

	Person p;
	ifs.read((char *)&p, sizeof(p));

	cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

system(“pause”);

“pause”这个系统命令的功能很简单,就是在命令行上输出一行类似于“Press   any   key   to   exit”的字,等待用户按一个键,然后返回。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值