十六周周记(书接上回)

4.2.2  构造函数的分类及调用

                分类:

                        。有参和无参(默认构造)

                        。普通和拷贝

                拷贝构造函数写法

					P(const person &P)
					{
						
					}

                分类示例:

						class pn 
						{
						public: 
							//构造函数 
							pn()//无参 
							{
								cout << "构造函数无参" << endl;
								
							}
							pn(int a)//有参 
							{
								name = a;
								cout << "构造函数有参" << endl;
								
							}
							//拷贝构造函数 
							pn(const pn &Person)
							{
								//将传入的人身上的所有属性,拷贝到我身上 
						//		name = pn.name;
							}
							//析构函数 (与类同名!!!) 
							~pn()
							{
								cout << "析构函数" << endl;
							}
							int name;
						};   

                        调用:

                                。括号法

                                。显示法

                                。隐式转换法

                        注意:

                                。默认构造函数调用时不加括号

                                。不用拷贝来初始化对象

                调用实例:

							//括号
							int a=10;
							pn p1;//无参(默认)构造函数调用不要加括号,若加括号,编译器则判断为一个函数的声明 ,不会认为是创建对象 
							pn p2(a);
							pn p3(p1); 
							
							cout << "输出p2的值为" << p2.name << endl; 
							cout << "输出p3的值为" << p3.name << endl; 
							//显示法
							pn p4;//无参 
							pn p5 = pn(10);//有参 
							pn p6 = pn(p4);//拷贝 
							pn(10); //匿名对象 在执行完当前语句后自动回收匿名对象 
							//pn(p4);		//不要用拷贝来初始化一个匿名对象 编译器认为pn p4 ==pn (p4),所以重复定义 
							//隐式转换法 
							pn p7 = 10;  //相当于 pn p7 = pn(10);
							pn p8 = p7; 

                分类及调用完整代码:

							#include<iostream>
							using namespace std;
							
							class pn 
							{
							public: 
								//构造函数 
								pn()//无参 
								{
									cout << "构造函数无参" << endl;
									
								}
								pn(int a)//有参 
								{
									name = a;
									cout << "构造函数有参" << endl;
									
								}
								//拷贝构造函数 
								pn(const pn &Person)
								{
									//将传入的人身上的所有属性,拷贝到我身上 
							//		name = pn.name;
								}
								//析构函数 (与类同名!!!) 
								~pn()
								{
									cout << "析构函数" << endl;
								}
								int name;
							};   
							//调用 
							int main()
							{
								//括号
								int a=10;
								pn p1;//无参(默认)构造函数调用不要加括号,若加括号,编译器则判断为一个函数的声明 ,不会认为是创建对象 
								pn p2(a);
								pn p3(p1); 
								
								cout << "输出p2的值为" << p2.name << endl; 
								cout << "输出p3的值为" << p3.name << endl; 
								//显示法
								pn p4;//无参 
								pn p5 = pn(10);//有参 
								pn p6 = pn(p4);//拷贝 
								pn(10); //匿名对象 在执行完当前语句后自动回收匿名对象 
							//	pn(p4);		//不要用拷贝来初始化一个匿名对象 编译器认为pn p4 ==pn (p4),所以重复定义 
								//隐式转换法 
								pn p7 = 10;  //相当于 pn p7 = pn(10);
								pn p8 = p7; 
								system("pause");
								return 0;
							}

4.2.3  拷贝构造的作用

                。使用一个创建完毕的对象来初始化一个新对象

                。值传递方式给函数参数传值

                。值方式返回局部变量

                实例:

				#include<iostream>
				using namespace std;
				class car 
				{
				public:
					car()
					{
						cout << "凯迪拉克" << endl; 
					}
					car(int speed)
					{
						cout << "迈凯伦" << speed << endl; 
					}
					car(const car &c)
					{
						speed = c.speed;
						cout << "比亚迪" << endl;
					}
					~car()
					{
						cout << "bmw" << endl;
					}
					int speed;
				};
				//使用一个创建完毕的对象来初始化一个新对象
				void test1()
				{
					car c1(10);
					car c2(c1);
					cout << "迈凯伦为" << c2.speed << endl;
				}
				//值传递方式给函数参数传值
				void round(car c)
				{
					
				}
				void test2()
				{
					car c;
					round(c);
				}
				//值方式返回局部对象 
				car round2()
				{
					car c1;
					cout << (int*)&c1 << endl;
					return c1;//创建一个新对象返回 
				 } 
				void test3()
				{
					car c = round2();
					cout << (int*)&c << endl;//打印地址,验证对象为函数中创建的新对象 
				}
				int main()
				{
				//	test1();
				//	test2();
					test3();	
					system("pause");
					return 0;
				}

4.2.4  构造函数调用规则

        默认情况下,c++编译器至少给一个类添加3个函数

        。默认构造函数(无参,空)

        。默认析构函数(无参,空)

        。默认拷贝构造函数,对属性进行拷贝

 

        注意:

        。如果自定义有参构造函数,c++不再提供默认无参,但会提供默认拷贝

        。如果自定义拷贝,c++不会再提供其他构造函数

4.2.5  深浅拷贝

        浅:简单的赋值拷贝

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

        浅拷贝带来的问题就是堆区的重复释放

        所以利用深拷贝让新对象与旧对象不指向同一块堆区空间

        实例:

#include<iostream>
using namespace std;
class room
{
public:
	room()
	{
		cout << "badroom(无参构造)" << endl;
	}
	room(int a , int Light)
	{
		space = a;
		light = new int(Light);
		cout << "livingroom(有参构造)" << endl;
	}
	~room()
	{
		//析构代码,将堆区开辟数据做释放操作
		
		cout << "washroom(析构)" << endl;
	}
	room(const room &r)
	{
		cout << "newroom(拷贝构造)" << endl;
		space = r.space;
		//深拷贝操作
		light = new int(*r.light);
		
	}
	int space;
	int *light;
};
void test()
{
	room r1(200,300);
	cout << "room1 have" << r1.space << "采光为" << *r1.light << endl;
	room r2(r1);
	cout << "room2 have" << r2.space << "采光为" << *r2.light << endl;
}
int main()
{
	test();
	system("pause");
	return 0;
}

4.2.6  初始化列表

话不多说,直接看码

				#include<iostream>
				using namespace std;
				class shoes
				{
				public:
					//传统办法 
				//	shoes(int a , int b , int c)
				//	{
				//	 	color = a;
				//	 	size = b;
				//	 	grand = c;
				//	}
					int color;
					int size;
					int grand;
					//列表初始化
					shoes(int a,int b,int c) :color(a) , size(b) , grand(c)
					{
						
					}
				};
				int main()
				{
					shoes s(10,45,20);
				//	shoes s;
					cout << s.color << s.size << s.grand ;
					system("pause");
					return 0;
				} 

4.2.7  类对象作为类成员

如结构体,一个类也能是另一个类的成员(类似结构体嵌套)

4.2.8  静态成员

成员变量或函数前加上static,则为静态

        静态成员变量:

                。所有对象共享同一份数据

                。编译阶段分配内存(全局区)

                。类内声明,类外初始化(类内static + 数据类型 + 变量名//类外 数据类型 + 类名(作用域) +::+变量名+数据

        静态成员函数:

                。所有对象共享同一个函数

                。静态成员函数只能访问静态成员变量!!!(函数体无法区分不同对象的成员变量)

4.3 C++对象模型和this指针

4.3.1 成员变量和函数的储存

        。静态不占内存

        。空对象占内存为1(为了区分空对象占内存的位置)

4.3.2 this指针

每一个非静态成员函数只会生成一份实例,也就是多个同类对象使用同一段代码,那这一份代码如何区分是哪个对象调用的自己呢?

可以使用this指针,解决上述问题

        。this指针指向被调用的成员函数所属的对象

        。this指针是一种隐含每一个非静态成员函数的指针

        。无需声明,直接调用

        。当形参和成员变量同名时,用this区分(一般情况下,类内名称可加上m_前缀表示成员变量或函数,用于区分)

				class noodles
				{
				public:
					noodles(string kind)
					{
						kind = kind;//报错,编译器认为三者为同一份
						//解决方法:
						this->kind = kind;//使用this指针区分 
						//m_kind = kind; //定义时区分 
					}
					string kind;
				//  string m_kind; 
				}; 
				//名称冲突 
				void test1()
				{
					noodles n1("lanzhou");
					cout << "这是" << n1.kind << "面" << endl; 
				}

                。在类的非静态成员函数中返回对象本身,可使用return *this

								class noodles
								{
								public:
									noodles(string kind)
									{
										kind = kind;//报错,编译器认为三者为同一份
										//解决方法:
										this->kind = kind;//使用this指针区分 
										//m_kind = kind; //定义时区分 
									}
									void kindof(noodles &n)
									{
										this->kind += n.kind;
									}
									string kind;
								//  string m_kind; 
								}; 
								//名称冲突 
								void test1()
								{
									noodles n1("lanzhou");
									cout << "这是" << n1.kind << "面" << endl; 
								}
								//返回对象本身
								void test2()
								{
									noodles n1("lanzhou");
									noodles n2("paomian");
									n2.kindof(n1);//如果我需要叠加多次呢
									//如下
									n2.kindof(n1).kindof(n1).kindof(n1);//此时编译器报错,void返回对象导致无法叠加 
									cout << n2.kind <<endl;
										
								} 
								int main()
								{
									test1();
									test2();
									system("pause");
									return 0;
}

当需要叠加多次,则需使用this指针返回本体达到目的(注意返回类型需更改为引用方式返回)

									#include<iostream>
                                    #include<string>
									using namespace std;
									class noodles
									{
									public:
										noodles(string kind)
										{
											kind = kind;//报错,编译器认为三者为同一份
											//解决方法:
											this->kind = kind;//使用this指针区分 
											//m_kind = kind; //定义时区分 
										}
										noodles& kindof(noodles &n)
										{
											this->kind += n.kind;
											//*this指向p2 
											return *this; 
										}
										string kind;
									//  string m_kind; 
									}; 
									//名称冲突 
									void test1()
									{
										noodles n1("lanzhou");
										cout << "这是" << n1.kind << "面" << endl; 
									}
									//返回对象本身
									void test2()
									{
										noodles n1("lanzhou");
										noodles n2("paomian");
										n2.kindof(n1);//如果我需要叠加多次呢
										//如下
										n2.kindof(n1).kindof(n1).kindof(n1);//此时编译器报错,void返回对象导致无法叠加 
										cout << n2.kind <<endl;
											
									} 
									int main()
									{
										test1();
										test2();
										system("pause");
										return 0;
									}

若返回类型不使用引用,而是值返回,那么每次返回相当于调用一次拷贝构造函数,结果也是无法叠加

4.3.3 空指针访问成员函数

						#include<iostream>
						using namespace std;
						class People
						{
						public:
							void showPeople()
							{
								cout << "this is People" << endl;
							 }
							void shouweiht()
							{
								cout << "this weight" << m_weight << endl;
							 } 
							 
							 int m_weight; 
						};
						void test1()
						{
							People *p = NULL;
							p->shouweiht();
							p->showPeople(); 
						}
						
						
						int main()
						{
							test1();
							system("pause");
							return 0;
                        }

报错,读取访问权限冲突,因为传入指针为空,所以在shouweight中m_weight没有实体

这种情况可采取以下操作

						#include<iostream>
						using namespace std;
						class People
						{
						public:
							void showPeople()
							{
								cout << "this is People" << endl;
							 }
							void shouweiht()
							{
								if(this==NULL)return;
								cout << "this weight" << m_weight << endl;
							 } 
							 
							 int m_weight; 
						};
						void test1()
						{
							People *p = NULL;
							p->shouweiht();
							p->showPeople(); 
						}
						
						
						int main()
						{
							test1();
							system("pause");
							return 0;
						}

加入判断,得以解决

4.4 友元

        作用:让一个函数或者类,访问到另一个类中的私有成员

        关键字:friend

        友元的实现:

        。全局函数做友元

		#include<iostream>
		#include<string>
		using namespace std;
		class Car
		{
			//告知编译器 boy全局函数是Car类的友元,可以访问私有内容
			friend void boy(Car * car);
			
		public:
			Car()
			{
				this->m_car1 = "本田";
				this->m_car2 = "法拉利"; 
			}
		public:
			string m_car1;
		private:
			string m_car2;	 
		};
		void boy(Car * car)
		{
			cout << "好友正在开" << car->m_car1 << endl;
			cout << "好友正在开" << car->m_car2 << endl;
		}
		void test()
		{
			Car c;
			boy(&c);
		 } 
		int main()
		{
			test();
			system("pause");
			return 0;
		}

        。类做友元

		#include<iostream>
		#include<string>
		using namespace std;
		class goodgay
		{
		public:
			goodgay();
			void visit();
		private:
			Car * car;
		}; 
		class Car
		{
			//告知编译器 boy全局函数是Car类的友元,可以访问私有内容
			friend void boy(Car * car);
			friend class goodgay;//类做友元 
			
		public:
			Car()
			{
				this->m_car1 = "本田";
				this->m_car2 = "法拉利"; 
			}
		public:
			string m_car1;
		private:
			string m_car2;	 
		};
		void boy(Car * car)
		{
			cout << "好友正在开" << car->m_car1 << endl;
			cout << "好友正在开" << car->m_car2 << endl;
		}
		goodgay::goodgay()
		{
			car = new Car; 
		}
		//类外写成员函数 
		void goodgay::visit()
		{
			cout << "好友正在开" << car->m_car1 << endl;
			cout << "好友正在开" << car->m_car2 << endl;
		}
		void test()
		{
		//	Car c;
		//	boy(&c);
			goodgay g;
			g.visit();
		 } 
		int main()
		{
			test();
			system("pause");
			return 0;
		}

        。成员函数做友元

        与上相同,使用friend关键字声明即可实现可访问

4.5 运算符重载!!!(重要)

对已有的运算符进行重新定义,赋予其新的功能,以适应不同的数据类型

4.5.1 加号运算符重载

作用:实现两个自定义数据类型的相加

成员函数实现

			#include <iostream>
			using namespace std;
			
			class Number {
			private:
			    int num;
			public:
			    Number(int n) : num(n) {}
			
			    // 1. 成员函数重载+
			    Number operator+(const Number& other) {
			        Number result(0);
			        result.num = this->num + other.num;
			        return result;
			    }
			
			    void display() {
			        cout << "Number: " << num << endl;
			    }
			};
			
			int main() {
			    Number num1(5);
			    Number num2(10);
			
			    Number sum = num1 + num2; // 使用重载的+号进行计算
			
			    sum.display(); // 输出结果
			    return 0;
			}

全局函数实现

			#include <iostream>
			using namespace std;
			
			class Number {
			private:
			    int num;
			public:
			    Number(int n) : num(n) {}
			
			    void display() {
			        cout << "Number: " << num << endl;
			    }
			
			    // 2. 全局函数重载+
			    friend Number operator+(const Number& num1, const Number& num2) {
			        Number result(0);
			        result.num = num1.num + num2.num;
			        return result;
			    }
			};
			
			int main() {
			    Number num1(5);
			    Number num2(10);
			
			    Number sum = num1 + num2; // 使用重载的+号进行计算
			
			    sum.display(); // 输出结果
			    return 0;
			}

4.5.2 左移运算符重载

作用:实现输出自定义数据类型

成员函数实现

			#include <iostream>
			using namespace std;
			
			class MyData {
			private:
			    int value1;
			    int value2;
			public:
			    MyData(int v1, int v2) : value1(v1), value2(v2) {}
			
			    // 1. 成员函数重载<<
			    friend ostream& operator<<(ostream& os, const MyData& data) {
			        os << "Custom Data: " << data.value1 << ", " << data.value2;
			        return os;
			    }
			};
			
			int main() {
			    MyData data(10, 20);
			    cout << data; // 使用重载的<<输出自定义数据类型
			    return 0;
			}

全局函数实现

			#include <iostream>
			using namespace std;
			
			class MyData {
			private:
			    int value1;
			    int value2;
			public:
			    MyData(int v1, int v2) : value1(v1), value2(v2) {}
			    
			    friend ostream& operator<<(ostream& os, const MyData& data);
			
			};
			
			// 2. 全局函数重载<<
			ostream& operator<<(ostream& os, const MyData& data) {
			    os << "Custom Data: " << data.value1 << ", " << data.value2;
			    return os;
			}
			
			int main() {
			    MyData data(10, 20);
			    cout << data; // 使用重载的<<输出自定义数据类型
			    return 0;
			}

4.5.3 递增运算符重载

作用:通过重载运算符,实现自己的整型数据

成员函数实现

			#include <iostream>
			using namespace std;
			
			class MyInt {
			private:
			    int value;
			public:
			    MyInt(int v) : value(v) {}
			
			    // 1. 成员函数重载++
			    MyInt& operator++() {
			        value = value + 1;
			        return *this;
			    }
			
			    void display() {
			        cout << "Value: " << value << endl;
			    }
			};
			
			int main() {
			    MyInt num(5);
			    ++num; // 使用重载的递增运算符
			
			    num.display(); // 输出结果
			    return 0;
			}

全局函数实现

			#include <iostream>
			using namespace std;
			
			class MyInt {
			private:
			    int value;
			public:
			    MyInt(int v) : value(v) {}
			
			    void display() {
			        cout << "Value: " << value << endl;
			    }
			
			    // 2. 全局函数重载++
			    friend MyInt& operator++(MyInt& num) {
			        num.value = num.value + 1;
			        return num;
			    }
			};
			
			int main() {
			    MyInt num(5);
			    ++num; // 使用重载的递增运算符
			
			    num.display(); // 输出结果
			    return 0;
			}

4.5.4 关系运算符重载

作用:使其通过重载关系运算符,实现两个自定义类型的对象进行对比操作

成员函数实现

			#include <iostream>
			using namespace std;
			
			class MyData {
			private:
			    int value;
			public:
			    MyData(int v) : value(v) {}
			
			    // 1. 成员函数重载==
			    bool operator==(const MyData& other) {
			        return this->value == other.value;
			    }
			};
			
			int main() {
			    MyData data1(10);
			    MyData data2(20);
			    MyData data3(10);
			
			    if (data1 == data2) {
			        cout << "data1 is equal to data2" << endl;
			    } else {
			        cout << "data1 is not equal to data2" << endl;
			    }
			
			    if (data1 == data3) {
			        cout << "data1 is equal to data3" << endl;
			    } else {
			        cout << "data1 is not equal to data3" << endl;
			    }
			
			    return 0;
			}

全局函数实现

#include <iostream>
using namespace std;

class MyData {
private:
    int value;
public:
    MyData(int v) : value(v) {}

    int getValue() const {
        return value;
    }
};

// 2. 全局函数重载==
bool operator==(const MyData& data1, const MyData& data2) {
    return data1.getValue() == data2.getValue();
}

int main() {
    MyData data1(10);
    MyData data2(20);
    MyData data3(10);

    if (data1 == data2) {
        cout << "data1 is equal to data2" << endl;
    } else {
        cout << "data1 is not equal to data2" << endl;
    }

    if (data1 == data3) {
        cout << "data1 is equal to data3" << endl;
    } else {
        cout << "data1 is not equal to data3" << endl;
    }

    return 0;
}

4.6 继承

当下一级类拥有上一级类的特性,并且拥有自己的特性时,可考虑使用继承,减少代码量

4.6.1 继承的基本语法

	// 基类
	class Base {
	public:
	    int baseVar;
	    void baseMethod() {
	        cout << "Base Method" << endl;
	    }
	};
	// 派生类
	class Derived : public Base {
	public:
	    int derivedVar;
	    void derivedMethod() {
	        cout << "Derived Method" << endl;
	    }
	};

4.6.2.继承方式

C++支持公有、保护和私有继承方式,通过访问权限修饰符指定:

	// 公有继承
	class Derived : public Base {
	    // ...
	};
	
	// 保护继承
	class Derived : protected Base {
	    // ...
	};
	
	// 私有继承
	class Derived : private Base {
	    // ...
	};

4.6. 3.继承中的对象模型

在继承中,派生类对象包含了基类的子对象。派生类对象中包含了基类的成员变量和成员函数。

4.6.4 继承中构造和析构顺序

在继承中,先调用基类的构造函数,再调用派生类的构造函数;析构的顺序与构造相反,先调用派生类的析构函数,再调用基类的析构函数。

	#include <iostream>
	using namespace std;
	
	class Base {
	public:
	    Base() {
	        cout << "Base Constructor" << endl;
	    }
	    ~Base() {
	        cout << "Base Destructor" << endl;
	    }
	};
	
	class Derived : public Base {
	public:
	    Derived() {
	        cout << "Derived Constructor" << endl;
	    }
	    ~Derived() {
	        cout << "Derived Destructor" << endl;
	    }
	};
	
	int main() {
	    Derived d;
	    return 0;
	}

4.6.5 继承同名成员的处理方式

在继承中,如果派生类中定义了与基类同名的成员函数或变量,会隐藏基类中的同名成员。如果要访问被隐藏的同名成员,可以使用作用域解析运算符`::`

	#include <iostream>
	using namespace std;
	
	class Base {
	public:
	    void display() {
	        cout << "Base Display" << endl;
	    }
	};
	
	class Derived : public Base {
	public:
	    void display() {
	        cout << "Derived Display" << endl;
	    }
	};
	
	int main() {
	    Derived d;
	    d.display(); // 调用派生类的display
	    d.Base::display(); // 调用基类的display
	    return 0;
	}

4.6.6 继承同名静态成员处理方式

静态成员在继承中是共享的,派生类可以直接访问基类的静态成员,而不会进行隐藏。

	#include <iostream>
	using namespace std;
	
	class Base {
	public:
	    static int value;
	};
	
	int Base::value = 5;
	
	class Derived : public Base {
	public:
	    void display() {
	        cout << "Value: " << value << endl; // 直接访问基类的静态成员
	    }
	};
	
	int main() {
	    Derived d;
	    d.display();
	    return 0;
	}

4.6.7 多继承语法

	class Base1 {
	    // ...
	};
	
	class Base2 {
	    // ...
	};
	
	class Derived : public Base1, public Base2 {
	    // ...
	};

4.6.8 菱形继承

菱形继承指的是一个派生类同时继承自两个直接或间接基类,而这两个基类又继承自同一个基类。这种情况可能引起二义性和资源浪费,可以通过虚拟继承来解决。

	#include <iostream>
	using namespace std;
	
	class A {
	public:
	    int value;
	};
	
	class B : public A {
	    // ...
	};
	
	class C : public A {
	    // ...
	};
	
	class D : public B, public C {
	    // ...
	};
	
	int main() {
	    D d;
	    d.B::value = 5; // 指定访问B类的value
	    d.C::value = 10; // 指定访问C类的value
	    cout << "Value from B: " << d.B::value << endl;
	    cout << "Value from C: " << d.C::value << endl;
	    return 0;
	}
	

4.7 多态

。多态分为两类
。静态多态:函数重载和 运算符重载属于静态多态,复用函数名。

。动态多态: 派生类和虚函数实现

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

 4.7.1 多态的基本语法

多态是指通过基类的指针或引用调用派生类的成员函数,实现不同对象以统一的方式响应消息的特性。在C++中,多态通过虚函数实现。

	class Base {
	public:
	    virtual void display() {
	        cout << "Display from Base" << endl;
	    }
	};
	
	class Derived : public Base {
	public:
	    void display() override {
	        cout << "Display from Derived" << endl;
	    }

4.7.2 纯虚函数和抽象类

纯虚函数是在基类中声明的虚函数,但没有给出具体实现,其目的是让派生类去实现该函数。包含纯虚函数的类称为抽象类,无法直接实例化对象。

	class AbBase {
	public:
	    virtual void pVFun() = 0; // 纯虚函数
	};
	
	class Derived : public AbBase {
	public:
	    void pVlF() override {
	        cout << "Derived  应用 pvfun" << endl;
	    }
	};

4.7.3 虚析构和纯虚析构

虚析构函数用于通过基类指针删除派生类对象时,确保正确调用派生类的析构函数。纯虚析构函数是一个没有函数体的虚析构函数,用于定义一个纯虚基类。

	class Base {
	public:
	    virtual ~Base() {
	        cout << "Base 析构" << endl;
	    }
	};
	
	class AbsBase {
	public:
	    virtual ~AbBase() = 0; // 纯虚析构函数声明
	};
	
	AbBase::~AbBase() {} // 纯虚析构函数定义

5 文件操作

程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放通过文件可以将数据持久化

C++中对文件操作需要包含头文件 < fstream >

文件类型分为两种:

1.文本文件- 文件以文本的ASCII码形式存储在计算机中2.二进制文件 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它们

操作文件的三大类:

1.ofstream: 写操作

2.ifstream: 读操作

3. fstream :读写操作

5. 1. 文本文件

5.1.1 写文件

写文件步骤如下

1.包含头文件

#include <fstream>

2.创建流对象

ofstream ofs;

3.打开文件

ofs.open("文件路径",打开方式);

4.写数据

ofs <<"写入的数据”

5.关闭文件

ofs.close();

文件打开方式

实例:

	#include <iostream>
	#include <fstream>
	using namespace std;
	
	int main() {
	    ofstream outFile("textfile.txt"); // 创建输出文件流对象
	
	    if (outFile.is_open()) {
	        outFile << "这是一个文件" << endl;
	        outFile << "能写" << endl;
	        outFile.close(); // 关闭文件
	        cout << " successfully." << endl;
	    } else {
	        cout << "Unable open ." << endl;
	    }
	
	    return 0;
}

5.1.2 读文件

读文件步骤如下:

1.包含头文件

#include <fstream>

2.创建流对象

ifstream ifs;

3.打开文件并判断文件是否打开成功ifs.open("文件路径",打开方式):

4.读数据

四种方式读取

5.关闭文件

ifs.close();

实例:

	#include <iostream>
	#include <fstream>
	#include <string>
	using namespace std;
	
	int main() {
	    ifstream inFile("textfile.txt"); // 创建输入文件流对象
	    string line;
	
	    if (inFile.is_open()) {
	        while (getline(inFile, line)) {
	            cout << line << endl; // 逐行读取并输出内容
	        }
	        inFile.close(); // 关闭文件
	    } else {
	        cout << "Unable  open " << endl;
	    }
	
	    return 0;
	}

5. 2 二进制文件

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

5.2.1 写文件

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

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

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

实例:

	#include <iostream>
	#include <fstream>
	using namespace std;
	
	struct Record {
	    int id;
	    char name[20];
	    double salary;
	};
	
	int main() {
	    ofstream outFile("binaryfile.dat", ios::binary); // 创建二进制输出文件流对象
	
	    if (outFile.is_open()) {
	        Record rec = {1, "彭于晏", 3500.50};
	        outFile.write(reinterpret_cast<char*>(&rec), sizeof(rec)); // 写入结构体数据
	        outFile.close(); // 关闭文件
	        cout << "successfully." << endl;
	    } else {
	        cout << "Unable open ." << endl;
	    }
	
	    return 0;
	}

5.2.2 读文件

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

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

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

实例:

	#include <iostream>
	#include <fstream>
	using namespace std;
	
	struct Record {
	    int id;
	    char name[20];
	    double salary;
	};
	
	int main() {
	    ifstream inFile("binaryfile.dat", ios::binary); // 创建二进制输入文件流对象
	    Record rec;
	
	    if (inFile.is_open()) {
	        inFile.read(reinterpret_cast<char*>(&rec), sizeof(rec)); // 读取结构体数据
	        cout << "ID: " << rec.id << endl;
	        cout << "名: " << rec.name << endl;
	        cout << "薪资: " << rec.salary << endl;
	        inFile.close(); // 关闭文件
	    } else {
	        cout << "Unable open ." << endl;
	    }
	
	    return 0;
	}

以上贴图及概念有部分来自b站黑马程序员

【黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难】https://www.bilibili.com/video/BV1et411b73Z?p=146&vd_source=1a0f1d0385352c94160379ddb0f8f7a1

这周的笔记先到这里

谢谢观看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值