C++核心编程--引用、函数高级、类和对象、文件操作

 
1、内存分区模型
    c++程序执行时,将内存大方向分为四个区域:
                代码区:存放函数体的二进制代码,由操作系统进行管理的
                全局区:存放全局变量和静态变量以及常量
                栈区:由编译器自动分配释放,存放函数的参数值,局部变量等
                堆区:由程序员分配和释放,若程序员不释放,程序结束时有操作系统回收
    内存四个区域意义:
                不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程
 
    程序运行前:
            在程序编译后,生成了exe代码可执行程序,未执行该程序前分为两个区域
 
1.1、程序运行前:全局区、代码区
            代码区:
                        存放cpu执行执行的机器指令
                        代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
                        代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令
 
           全局区:
                        全局变量和静态变量存放在此
                        全局区还包括常量区,字符串常量和其他变量也存放在此
                        该区域的数据在程序结束后由操作系统释放
 
                        全局区:全局变量、静态变量、static关键字;常量:字符串常量、const修饰的全局变量(全局常量)。
                        不在全局区:局部变量,const修饰的局部变量(局部常量)。
 
                总结:1、在程序运行之前分为全局区和代码区
                          2、代码区特点是共享和只读
                          3、全局区存放全局变量、静态变量、常量
                          4、常量区存放const修饰的全局常量和字符串常量
 
 
1.2、程序运行后:栈区、堆区
 
            栈区:由编程器自动分配释放、存在函数的参数值,局部变量等;
                      注意事项:不要返回局部变量地址,栈区开辟的数据由编译器自动释放
            
            第一次可以打印正确的数字,是因为编译器做了保留,第二次这个数据就不保留了。
 
           堆区:由程序员分配和释放,若程序员不释放,程序结束时有操作系统回收。在c++中,利用new关键字开辟内存。
 
1.3、new操作符
            
        C++中利用new操作符在堆区开辟数据,堆区开辟的数据,由程序员手动开辟,手动释放,释放利用操作符delete
        语法:new  数据类型
        利用new创建的数据,会返回该数据对应的类型的指针
        
              int a    =    new  int(10);  10 代表新建数据10    释放数据 delete  a;
        new创建数组:
              int arr  =    new  int[10];       10代表十个元素    释放数据 delete[]   arr;
 
 
2、引用
 
2.1、引用基本语法
 
        引用:给变量起别名;
        语法:数据类型  &别名 = 原名
 
2.2、引用注意事项
 
        1、引用必须初始化;int  &b;错误
        2、引用一旦初始化后,就不可以更改
 
2.3、引用做函数参数
 
        作用:函数传值时,可以利用引用的技术让形参修饰实参;函数名(数据类型 &变量,数据类型 &变量)。
        优点:可以简化指针修改实参
 
        总结:通过引用参数产生的效果通按地址传递是一样的,引用的语法更简单
 
2.4、引用做函数返回值
        
        1、不要返回局部变量的引用
                局部变量:存放栈区,函数运行完释放
        2、函数的调用可以作为左值;返回静态变量引用。
                左值:等号左边的数据
                如果函数的返回值是引用,这个函数调用可以作为左值存在;
 
                静态变量:存放全局区,程序运行完系统释放;
 
2.4、引用的本质
 
        本质:在C++内部实现就是一个指针常量;
        int &ref = a;  相当于 int* const   ret    = &a;
                    指针常量是指针的指向不可改,也说明为什么引用不可更改。
        ref  = 10;
                    内部发现是ref是引用,自动帮我们转化为*ref = 20;
 
        结论:c++推荐使用引用技术,因为语法方便,引用的本质是指针常量,但是所有的指针操作编译器帮我们做了。
 
 
2.5、常量引用
 
        常量引用使用场景:用const来修饰形参,防止误操作
 
        int & ref = 10;错误;引用必须是一块合法的内存空间。
 
       const  int & ref = 10;加上const之后,编译器将代码修改  int  temp = 10;const int & ref = temp;
        加上const之后只读,不可修改;
 
        
3、函数高级
        
        3.1、函数的默认参数
                语法:返回值类型   函数名 (参数 = 默认值){}
                如果我们自己传入了数据,就用自己的数据,如果没有,那就用默认值
 
              注意事项:
                            1、 如果某个位置已经有了默认值,那么这个位置往后,从左到右都必须有默认值。                
                            2、如果函数的声明有默认参数,函数的实现就不能有默认参数。声明和实现只能有一个默认参数。
                
 
        3.2、函数占位参数
                
                c++中函数的形参列表里可以有占位参数,用来占位,调用函数时必须填补位置
                语法:返回值类型  函数名(数据类型){}
 
         3.3、函数重载
            
                作用:函数名可以相同,提高复用性
                函数重载满足的条件:
                                                1、同一个作用域
                                                2、函数名相同
                                                3、函数参数类型不同或者个数不同或者顺序不同
                注意:函数的返回值不可以作为函数重载的条件
                
           3.4、函数重载注意事项
            
                1、引用作为重载条件
                    (int   &a);
                    (const   int  &a);
                    传变量会进入(int  &a),因为变量可读可写,const修饰的只读不可写;直接传数字可以进入(const   int  &a);
 
                2、函数重载碰到默认参数
                    当函数碰到默认参数,会产生二义性,报错,尽量避免这种情况
 
4、类和对象
 
     c++面向对象的三大特性:封装、继承、多态
 
        4.1、封装
 
                封装的意义:将属性和行为作为一个整体,表现生活中的事物;将属性和行为加以权限控制。
 
                封装意义一:在设计类的时候,属性和行为写在一起,表现事物
                语法:class  类名{   访问权限:属性  /    行为};
                
                访问权限:
                            公共权限  public         成员  类内可以访问    类外可以访问
                            保护权限  protected   成员  类内可以访问    类外不可以访问   儿子可以访问父亲的保护内容
                            私有权限  private        成员  类内可以访问   类外不可以访问    儿子不可以访问父亲的私有内容
 
                class和struct区别:
                                            struct  默认权限是  公有 public    因此可以访问
                                            class    默认权限是  私有private   类外不能访问
 
                 成员设置私有优点:
                                        1、将所有成员属性设置为私有,可以自己控制读写权限
                                        2、对于写权限,我们可以检测数据的有效性
                
            4.2、对象的初始化和清理
 
                   1、构造函数和析构函数
                        构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用。
                        构造函数语法:类名 (){}
                                1、构造函数没有返回值也不写void
                                2、函数名字和类名相同
                                3、构造函数可以有参数,因此可以发生重载
                                4、程序在调用对象时候会自动调用构造,无需手动调用,而且只会调用一次
                        
                        按照参数分:有参构造、无参构造
                        按照类型分:普通构造、拷贝构造
 
                        拷贝构造函数:类名(const   类名  &对象){}
                      
                        析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作。
                         析构函数语法:~类名 (){}
                                1、析构函数没有返回值也不写void
                                2、函数名字和类名相同,在名称前加上~
                                3、构造函数不可以有参数,因此不可以发生重载
                                4、程序在对象销毁前会自动调用构造,无需手动调用,而
 
                   2、调用构造的三种方法:
                       1、括号法
                            类名  P1;  默认构造函数
                            类名  p2(10);有参构造
                            类名  p3(p2);拷贝构造    
 
                        注意事项1:
                                调用默认构造函数时,不要加(),因为会认为是一个函数声明,不会创建对象。
                        
                        2、显示法
                            类名  P1;  默认构造函数
                            类名  p2 = 类名(10);有参构造
                            类名  p3 = 类名(p2);拷贝构造    
 
                            类名(10);匿名对象   特点:当前行执行结束后,系统会立即回收掉匿名对象
                            注意事项2
                                   不要利用拷贝构造函数,初始化匿名对象 ,编辑器会认为类名(p3) ===类名 p3;会认为是对象声明
 
                            类名(p3);错误;
 
                            3、隐式转换法
                                 类名  p4 = 10;     相当于 写了  类名 p4 = 类名(10):有参构造
                                 类名   p5 = p4;    拷贝构造
 
                   3、拷贝构造函数调用时机
                    c++中拷贝构造函数调用时机通常有三种情况
                            1、使用一个已经创建完毕的对象来初始化一个新对象
                            2、值传递的方式给函数参数传值;当实参传递时,临时拷贝
                            3、以值方式返回局部对象;return的时候拷贝一个新的返回
                            
                   4、构造函数调用规则
 
                    默认情况下,C++编译器至少给一个类添加三个函数:
                            1、默认构造函数(无参,函数体为空)
                            2、默认析构函数(无参,函数体为空)
                            3、默认拷贝构造函数,对属性值进行值拷贝
 
                    构造函数调用规则:
                            1、如果用户定义有参数,c++不提供默认无参构造,但是会提供默认拷贝构造
                            2、如果用户定义拷贝构造函数,c++不会提供其他构造函数
 
 
 
                   5、深拷贝与浅拷贝
                    
                        浅拷贝:简单的赋值拷贝操作
                        深拷贝:在堆区重新申请空间,进行拷贝操作
                
                        如果利用编译器提供的拷贝构造函数,会做浅拷贝。浅拷贝的问题:堆区内存重复释放。
                        
                   6、初始化列表
 
                        作用:C++提供了初始化列表语法,用来初始化属性
                        语法:构造函数():属性1(值1),属性2(值1),……{}
 
 
                   7、类对象作为类成员
 
                        当其他类对象作为本类成员,构造时候先构造其他类对象,在构造自身,析构顺序与构造相反。
 
                   8、静态成员
 
                        静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员
                        静态成员分为:
                                1、静态成员变量
                                           ○  所有对象共享同一份数据
                                           ○  在编译阶段分配内存
                                           ○  类内声明,类外 初始化
                                2、静态成员函数
                                           ○  所有对象共享的一个函数
                                                     ○  静态成员只能访问静态成员变量
                        
 
                        静态成员函数两种访问方式:1、通过对象访问  2、通过类名访问
                        静态成员函数也是有访问权限的:私有权限下类外也无法访问。
 
 
            4.3、 C++对象模型和this指针
 
                    1、成员变量和成语函数分开储存
                            
                            在C++中,类内成员变量和成员函数分开储存,只有非静态成员变量才属于类的对象上。
 
                            空对象占用内存空间为:1;c++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置。
 
                            非静态成员变量,属于类的对象上;静态成员函数,不属于类对象上;非静态成员函数,不属于类对象上。
 
 
                    2、this指针的用途
                            this指针指向被调用的成员函数所属的对象。
                            用途:1、当形参和成员变量同名时,可用this指针来区分
                                       2、在类的非静态成员函数中返回对象本身,可使用return * this;
                            
                            用return *this的时候,返回值类型是的引用 :类名 &函数名{return *this};返回值的形式   类名函数名,是临时拷贝新对象;返回引用不会创建新的对象。
 
 
                    3、空指针调用成员函数
                            C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针;如果用到this指针,需要加以判断保证代码的健壮性
 
 
                    4、const修饰成员函数
 
                            常函数:
                                       ○ 成员函数后加const后我们会称之为常函数
                                       ○ 常函数不可以修改成员属性
                                       ○ 成员属性声明时加关键字mutable后,在常函数中依然可以修改,常对象下也可以修改
                            常对象:
                                        ○ 声明对象前加const称之为常对象
                                        ○ 常对象只能调用常函数
 
            4.4、 友元
                            友元的目的就是让一个函数或者类访问另一个类中私有成员
                            友元的关键字为 friend
                            友元的三种实现:
                                            ○ 全局函数做友元    friend    返回值  函数名();
                                            ○ 类做右元     friend   class  类名;
                                            ○ 成员函数做友元     friend   class  类名;
 
            4.5、 运算符重载
                       运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
 
                        1、加号运算符重载
                                作用:实现两个自定义数据类型相加的运算
                                ○ 成员函数重载+加号
                                            Person  operator+(Person  &p){
                                                              Person temp;                                                                                                     temp.A = this.A + p.A;
                                                              temp.B = this.B + p.B;                        
                                            }
 
                                            调用:Person  p3 = p1.operator+(p2);
                                            简化为:Person  p3 = p1 + p2;
 
                               ○  通过全局函数重载+
                                    
                                         Person  operator+(Person  &p1,Person  &p2){
                                                              Person temp;                                                                                                     temp.A = p1.A + p2.A;
                                                              temp.B = p1.B + p2.B;                        
                                            }
                                            调用:Person  p3 =operator+(p1,p2);
                                            简化为:Person  p3 = p1 + p2;
 
                                总结:对于内置的数据类型的表达式的运算符是不可能改变的;不要滥用运算符重载。
                                             
                        2、左移运算符重载
                            作用:可以输出自定义的数据类型
 
                            左移运算符只能用全局函数来重载左移运算符
                            void   operator<<( ostream  &cout    ,Person  &p){
                                        cout <<"m_A = "<<p.m_A<<"m_B = "<<p.m_B;
                            }不能链式输出<<endl;
                            
                            返回自身引用,就可以链式输出<<endl;
                            ostream  &  operator<<( ostream  &cout    ,Person  &p){
                                        cout <<"m_A = "<<p.m_A<<"m_B = "<<p.m_B;
                                        return cout;
                            }
 
 
                        3、递增运算符重载
                                作用:通过重载递增运算符,实现自己的整型数据
                                前置递增:返回引用是为了一直对一个数据进行递增操作
                                MyInteger & operator++(){
                                                m_Num++;
                                                return    *this;
                                }先计算后返回
 
                                后置递增:返回值,因为临时局部变量函数运行完释放。
                                   MyInteger  operator++(int){
                                                MyInteger    temp = m_Num;
                                                m_Num++;
                                                return    temp;
                                } 先记录后计算最后返回记录的值
 
                        4、递增运算符重载
 
                            C++ 编译器至少 给一个类添加四个函数:
                                    1、默认构造函数(无参,函数体为空)
                                    2、默认析构函数(无参,函数体为空)
                                    3、默认拷贝构造函数,对属性值进行值拷贝
                                    4、赋值运算符  operator=,对属性进行值拷贝
 
                            如果类中属性指向堆区,做赋值操作时也会出现深浅拷贝问题
                                            
                                  例如:     Person&   operator=(Person  &p){
                                                           if(m_Age  !=   NULL){
                                                                delete m_Age;
                                                               m_Age = NULL;
                                                            }   
                                                       m_Age = new int (*p.m_Age);                                                                              return *this;
                                            }
 
                        5、关系运算符重载
                            作用:重载关系运算符,可以让两个自定义类型对象进行对比操作
                                                重载等于
                                              bool   operator==(Person  &p){
                                                    if(this->m_Name ==p->m_Name&&
                                                           this->m_Age ==p->m_Age&     ){
                                                              return   ture;
                                                            }   
                                                       return false;
                                            }
                                                重载不等于
                                              bool   operator==(Person  &p){
                                                    if(this->m_Name ==p->m_Name&&
                                                           this->m_Age ==p->m_Age&     ){
                                                              return   false;;
                                                            }   
                                                       return true;
                                            }
 
                        6、函数调用运算符重载
                                ○ 函数调用运算符()也可以重载
                                ○ 由于重载后使用的方式非常像函数的调用,因此称之为仿函数
                                ○ 仿函数没有固定写法,非常灵活
 
                                匿名对象:类名()创建匿名对象,运行完就释放
                                                类名()();匿名对象调用仿函数
 
 
            4.6、 继承
                    继承是面向对象三大特性之一
 
                    1、继承的基本语法
                            继承的好处:减少重复代码
                            语法:class  子类:继承方式  父类
                            子类  也称之为  派生类
                            父类  也称之为  基类
                            
                            派生类中的成员,包含两大部分:
                                        一类是从基类继承过来的,一类是自己增加的成员
                                        从基类继承过过来的表现其共性,而新增的成员体现了其个性。
 
                    2、继承方式
                            父类私有的子类无法访问
                            公共继承:父类中的公共权限成员    到子类中依然是公共权限
                                             父类中的保护权限成员    到子类中依然是保护权限
                                             父类中的私有权限成员    子类中访问不到
 
                            保护继承:父类中的公共权限成员    到子类中变为保护权限
                                             父类中的保护权限成员    到子类中依然是保护权限
                                             父类中的私有权限成员    子类中访问不到
 
                            私有继承:父类中的公共权限成员    到子类中变为私有权限
                                             父类中的保护权限成员    到子类中变为私有权限
                                             父类中的私有权限成员    子类中访问不到
 
 
                    3、继承中的对象模型
                            父类中所有非静态成员属性都会被子类继承下去
                            父类中私有成员属性,是被编译器给隐藏了,因此是访问不到,但是确实被继承下去了
 
 
                    4、继承中的构造和析构顺序
                            子类继承父类后, 当创建子类对象,也会调用父类的构造函数
                            继承中的构造和析构的调用顺序如下:
                                        先构造父类,在构造子类,析构的顺序与构造的顺序相反
 
                   5、继承同名成员的处理方式
                            访问子类同名成员    直接访问即可
                            访问父类同名成员    需要加作用域;子类对象名.父类::成员名。
                            如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数。
 
                            总结:1、子类可以直接访问到子类中的同名成员
                                      2、子类对象加作用域可以访问到父类同名成员
                                      3、当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数      
  
 
 
 
 
 
 
 
 
                   6、继承同名静态成员的处理方式
                             静态成员和非静态成员出现同名,处理方式一致
                             访问子类同名成员    直接访问即可
                             访问父类同名成员    需要加作用域;子类对象名.父类::成员名。
                            同名静态成员的调用:
                                    1、通过对象访问
                                        子类静态成员调用:子类对象.静态成员
                                        父类静态成员调用:子类对象.父类名::静态成员
                                     2、通过类名访问
                                        子类静态成员调用:子类名::静态成员
                                        父类静态成员调用:子类名::父类名::静态成员
                                                                    第一个::代表通过类名方式访问
                                                                    第二个::代表访问父类作用域下 
                            同名静态成员函数的调用:
                                    1、通过对象访问
                                        子类静态成员调用:子类对象.静态函数
                                        父类静态成员调用:子类对象.父类名::静态函数
                                     2、通过类名访问
                                        子类静态成员调用:子类名::静态函数
                                        父类静态成员调用:子类名::父类名::静态函数
                                                                    第一个::代表通过类名方式访问
                                                                    第二个::代表访问父类作用域下 
 
                            子类出现和父类同名的静态成员函数,也会隐藏父类所有的同名成员函数;如果想要访问父类中被隐藏同名函数,需要加作用域。
 
                   7、多继承语法
                            语法:class  子类:继承方式   父类1,继承方式    父类2,……
                            多继承可能会引发同名成员出现,需要加作用域来区分
                            通过Vs2017 开发者工具,进到保存cpp文件的位置,cl  /d1   reportSingleClassLayout__类名___"文件名"。
                            通过这个方式查看类占了多少内存空间,分别都是什么。
 
                   8、菱形继承
                            菱形继承概念:
                                    两个派生类继承同一个基类
                                    又有某个类同事继承两个派生类
                                    这种继承被称为菱形继承,或者钻石继承
                            菱形继承会产生二义性,利用虚继承来解决问题。
                            继承之前  加上关键字 virtual 变为虚继承
                            
            4.7、 多态
                    多态是面向对象三大特性之一
                    1、多态的基本概念
                            多态分为两类
                                    ○ 静态多态:函数重载和运算符重载属于静态多态,复用函数名
                                    ○ 动态多态:派生类和虚函数实现运行时多态
                            静态多态和动态多态区别:
                                   ○ 静态多态的函数地址早绑定 - 编译阶段确定函数地址
                                    ○ 动态多态的函数地址晚绑定 - 运行阶段确定函数地址
 
                            函数前面加上virtual关键字,变成虚函数,那么编译器的时候就不能确定函数调用了
 
                            动态多态满足条件:
                                     1、有继承关系
                                     2、子类重写父类的虚函数
                                     重写 :函数返回值类型、函数名、参数列表全部一致称为重写
        
                            动态多态使用:父类的指针或引用  执行子类对象
                                        
                    2、多态案例一——计算机类
                            多态的优点:代码组织结构清晰;可读性性强;利于前期和后期的扩展以及维护
            
                    3、纯虚函数和多态类
                            通常父类的虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数。
                            纯虚函数语法:virtual 返回值类型  函数名  (参数列表) = 0;
                            当类中有了纯虚函数,这个类也称为抽象类;
                            抽象类特点:
                                            1.无实例化对象
                                            2.子类必须重写抽象类中的纯虚函数,否则也属于抽象类
 
                    4、多态案例二——制作饮品
                             案例描述:
                                            制作饮品的大致流程:煮水- 冲泡 - 倒入杯中  - 加入佐料
                            利用多态技术实现本案例,提供抽象类制作饮品基类,提供子类制作咖啡和茶叶。
 
                    5、虚析构和纯虚析构
                            多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码,解决方式:将父类中的析构函数改为虚析构或者纯虚析构。
 
                            虚析构和纯虚析构共性:
                                                        1、可以解决父类指针释放子类对象
                                                        2、都需要有具体的函数实现
                            虚析构和纯虚析构区别:
                                                        1、如果是纯虚析构,该类属于抽象类,无法实例化对象
                            虚析构语法:
                                            virtual ~类名(){}
                            纯虚析构语法:
                                            virtual ~类名()= 0;纯虚析构声明
                                            类名::~类名(){}   纯虚析构类外实现
 
                            纯虚析构    需要声明也需要实现
                            有了纯虚析构之后,这个类也属于抽象类,无法实例化对象
 
                            总结:
                                    1、虚析构和纯虚析构就是用来解决通过父类指针释放子类对象
                                    2、如果子类中没有堆区数据,可以不写虚析构或纯虚析构
                                    3、拥有纯虚析构函数的类也属于抽象类
 
                    4、多态案例三——电脑组装
                            案例描述:电脑主要组成部件为CPU(用于计算),显卡(用于显示),内存条(用于储存);将每个零件封装出抽象类,并且提供不同的厂商生产不同的零件,例如Intel厂商和lenovo厂商;创建电脑类提供让电脑工作的函数,并且调用每个零件工作的接口,测试时组装三台不同的电脑进行工作。
 
5、文件操作
            c++对文件操作需要包含头文件<fstream>
            文本类型分为两种:
                            1、文本文件   文件以文本的ASCLL码形式存储在计算机中
                            2、二进制文件  文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂他们
 
            操作文件的三大类:
                            1、ofstream:写操作
                            2、ifstream:读操作
                            3、fstream:读写操作
 
                    5.1、文本文件
                                写文件步骤:
                                            (1)包函头文件:#include <fstream>
                                            (2)创建流对象:ofstream ofs;
                                                        ofstream ofs("打开路径",打开方式);
                                            (3)打开文件:ofs.open("打开路径",打开方式);
                                            (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;                                                                                    ifstream ifs("打开路径",打开方式);
                                            (3)打开文件:ifs.open("打开路径",打开方式);
                                          is_open函数判断文件是否打开成功
                                            (4)读数据:四种方式读取
                                            (5)关闭文件:ifs.close();
 
                                读数据:
                                            第一种: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(  getline(ifs,buf )  ){
                                                    cout<<buf<<endl;
                                            }
    
                                            第四种:char c;
                                            while(  (c=ifs.get()) != EOF ){
                                                    cout<<c;
                                            }
 
                    5.2、二进制文件
                          打开方式指定为 ios::binary
 
                          写文件:
                          二进制写文件主要利用流对象调用成员函数write
                          函数类型:ostream&  write(const  char * buffer,int  len) 
                          参数解释:字符指针buffer指向内存中一段存储空间,len是读写的字节数
                            string  会容易报错    用char数组
 
                            二进制方式写文件:
                                     (1)包函头文件:#include <fstream>
                                     (2)创建流对象:ofstream ofs;                                                                                   ofstream ofs("打开路径",打开方式);
                                     (3)打开文件:ofs.open("打开路径",打开方式);
                                     (4)写文件:ofs.write((const char*)&p,sizeof(类名));
                                     (5)关闭文件:ifs.close();
                        
                          读文件:
                          二进制读文件主要利用流对象调用成员函数read
                          函数类型:istream&  read(char * buffer,int  len) 
                          参数解释:字符指针buffer指向内存中一段存储空间,len是读写的字节数
                            二进制方式读文件:
                                      (1)包函头文件:#include <fstream>
                                      (2)创建流对象:ifstream ifs;                                                                                    ifstream ifs("打开路径",打开方式);
                                       (3)打开文件:ifs.open("打开路径",打开方式);
                                      is_open函数判断文件是否打开成功
                                        (4)读文件:ifs.read((char *)&p,sizeof(类名));
                                        (5)关闭文件:ifs.close();
 
 
 
 
 
 
 
 
 
 
posted @ 2020-09-27 13:57  不负华年  阅读(359)  评论(0)    收藏  举报