c++核心编程
c++核心编程

c++核心编程

1.内存分区模型

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

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

栈区:由编译器自动分配和释放,存放函数的参数值,局部变量。

堆区:由程序员分配和释放,存放函数的参数值。(主要利用new在堆区开辟内存)

1.1new运算符

#include<iostream>
using namespace std;
int* func() {
    int* a = new int(10);
    return a;
}
int main() {
    int* p = func();
    cout << *p << endl;
    return 0;
}

如果想释放堆区的数据,用delete。

2.引用

2.1引用的基本使用

语法:数据类型 & 别名=原名

2.2引用注意事项

引用必须初始化

引用在初始化后,不可以更改

int main() {
    int a = 10;
    int b = 20;
    int& c = a;
    c = b;
    cout << c << a << b;
    return 0;
}

2.3引用做函数返回值

注意:不要返回局部变量引用

用法:函数调用作为左值

int& text01() {
    int static a=10;
    return a;
}
int& text02() {
    int b = 20;
    return b;//不能返回临时变量
}
int main() {
    int& ref = text01();
    cout << ref << endl;
    cout << ref << endl;
    text01() = 1000;//如果函数返回值是引用,则函数可以做左值
    cout << text01() << endl;
    int& ref1 = text02();
    cout << ref1 << endl;
    cout << ref1 << endl;
    return 0;
}

2.4引用的本质

本质:指针常量

void func(int& ref) {
    ref = 100;
}
int main() {
    int a = 10;
    int& ref = a;//制度转换为 int* const ref=&a,指针常量不可更改
    ref = 20;//转换为 *ref=20
    cout << ref << endl;
    cout << a << endl;
    func(a);
    return 0;
}

3.类和对象

c++面向对象的三大特性:封装,继承,多态

c++认为万事万物都有对象,对象上有其属性和行为

3.1封装

const double pi = 3.14;
class circle{
public://权限
    int r;//属性
    double zhouchang() {
        return 2 * pi * r;//行为
    }
};
int main() {
    circle a;
    a.r = 10;
    cout<<a.zhouchang();
    return 0;
}

封装意义二:

类在设计时,可以把属性和行为放在不同的权限下,加以控制

访问权限:

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

保护权限 protected–>成员类内可以访问,类外不可以访问,儿子可以访问父亲保护的内容

私有权限private—-> 成员类内可以访问,类外不可以访问 儿子不可以访问父亲的私有内容

class preson {
public:
    string m_name;

protected:
    string m_car;
public:
    void func() {
        m_name="杭三";
        m_car="皮卡"; //类内可以访问
    }
};

int main() {
    preson p1;
    p1.m_name = "李四";
    p1.func();
    //p1.car="宝马",私有权限类外不可以访问
    return 0;
}

3.1.2 struct和class的区别

唯一区别:默认访问权限不同

struct:默认公共权限

class:默认私有权限

3.1.3 成员属性设置私有

class student{
public:
    void getname(string id) {
        name = id;
    }
    string printname() {
        return name;
    }
    int getage() {
        return age;
    }
    void getidole(string s) {
        idole = s;
    }
protected:
    string name;//可读可写
    int age=18;//只读
    string idole;//只写
};
int main() {
    student a;
    a.getname("张三");
    cout << a.printname()<< endl;
    cout << a.getage() << endl;
    a.getidole("李四");
    return 0;
}

3.2 对象的初始化和清理

3.2.1 构造函数和析构函数

这两个函数会被编译器自动调用,完成对象的初始化和清理工作。

构造函数:创建对象时为对象的成员赋值,编译器自动调用

析构函数:在对象销毁前自动调用。

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

1.没有返回值

2.函数名称与类名相同

3.可以重载

4,只能调用一次。

析构函数:~类名(){}

1.没有返回值

2.函数名称与类名相同,在名称前加上符号~

3.不可以有参数,不能发生重载

4.只会调用一次

3.2.2 函数分类以及调用

class person {
public:
    person() {
        cout << "无参构造函数的调用" << endl;
    }
    person(int a) {
        age = a;
        cout << "有参构造函数调用" << endl;
    }
    person(const person &p) {
        age = p.age;
        cout << "person的拷贝构造函数的调用" << endl;
    }
    ~person() {
        cout << "析构函数的调用" << endl;
    }
    int age;
};
void text01() {
    //括号法
    //person p1;
    //person p2(10);
    //person p3(p2);
    //显示法
    person p1;
    person p2 = person(10);
    person p3 = person(p2);
    //隐式转换法
    person p4 = 10;
    person p5 = p4;
}

3.2.3 拷贝构造函数的调用时机

  • 使用一个创建完毕的对象来初始化一个新对象
  • 通过值传递的方式给函数参数传值
  • 以值方式返回局部对象
void dowork(person 
p) {
}
void text02() {
    person p;
    dowork(p);
} //值传递,拷贝和默认构造函数

3.2.4 构造函数的调用规则

如果我们写了有参构造函数,系统不会提供默认构造,但依然会提供拷贝构造函数

如果写了拷贝构造函数,那么编译器不再提供其他的函数。

3.2.5 深拷贝与浅拷贝

image-20250615115225382

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

person(const person& p) {
    cout << "person拷贝构造函数的调用" << endl;
    m_age = p.m_age;
    //深拷贝操作
    m_height=new int(*p.m_height);
}

3.2.6 初始化列表

class person {
public:
    person(int a,int b) :m_a(a), m_b(b){}
    int m_a, m_b;
};
int main() {
    person p(20,10);
    cout << p.m_a << p.m_b;
    return 0;
}

3.2.7 类对象作为类成员

class phone {
public:
    phone(string pname) {
        m_pname = pname;
        cout << "phone的构造函数调用" << endl;
    }
    ~phone() {
        cout << "phone析构函数的调用" << endl;
    }
    string m_pname;
};
class person {
public:
    person(string name,string Pname ):m_name(name),m_phone(Pname){
        cout << "person函数构造调用" << endl;
    }
    ~person() {
        cout << "person析构函数的调用" << endl;
    }
string m_name;
phone m_phone;
};
//当其他类函数作为一个类的成员时,优先调用其他类的构造函数,析构函数则相反
void text01() {
    person p("张三", "苹果max");
    cout << p.m_name << p.m_phone.m_pname;
}

3.2.8 静态成员

  • 静态成员变量:所有对象共享一份数据,在编译阶段分配内存,类内声明,类外初始化(有访问权限)
  • 静态成员函数:所有对象共享同一个函数,静态成员函数只能访问
class person{
public:
    static int m_a;
};
int person::m_a = 100;
void text01() {
    person p;
    cout << p.m_a << endl;//直接访问
    cout << person::m_a << endl;//间接访问
}
class person {
public:
    static void func() {
        a = 100;//静态成员函数可以访问
        //b = 2000 静态成员函数不能访问非静态常量,无法区分是哪个对象的
        cout << "静态函数调用" << endl;
    }
    static int a;
    int b;
    //静态函数有访问权限
};
void text01() {
    person p;
    p.func();
    person::func();
}

3.3 c++对象模型和this指针

class person {
    int m_a;
    static int m_b;//不属于类的对象
    void func() {//非静态成员函数不属于类的对象
    }
    static void func1() {};//静态成员函数不属于类的对象
};
int person::m_b = 100;
void text01() {
    person p;
    //c++编译器会给每个空对象分配一个字节空间,是为了区分空对象占内存的位置
    //每个空对象也应该有一个独一无二的内存地址
    cout << sizeof(p) << endl;
};

3.3.1 this 指针

class person {
public:
    person(int age) {
        //this指针指向的是被调用的成员函数所属的对象
        this->age = age;
    }
    person& personage(person &p) {//用引用做函数返回值,返回类本身
        this->age += p.age;//若返回值,则会拷贝一个新的person类型,无法对原类成员进行修改
        return *this;
    }
    int age;
};
void text01() {
    person p(18);
    cout << p.age;
};
void text02() {
    person p1(19);
    person p2(10);
    //链式编程思想
    p2.personage(p1).personage(p1).personage(p1);
    cout << p2.age << endl;
}

3.3.2 空指针访问成员函数

3.3.3 const指针修饰成员函数

常函数:

  • 在成员函数后加const,修饰this指针,使得它指向的值不可以修改
  • 常函数内不能修改成员属性
  • 成员属性声明时加关键字mutable后,在常函数中依然可以修改

常对象:

  • 声明对象前加const为常对象
  • 常对象只能调用常函数
class person{
public:
    void func() {
        cout << "调用" << endl;

    }
    void func1(int age) const{
        m_abs = age;
    }
    int m_age;
    mutable int m_abs;//特殊变量,在常函数中可以修改值
};
//常对象只能调用常函数
void text01() {
    const person p;
    p.m_abs = 199;
    p.func1(10);
    cout << p.m_abs << endl;
}

3.4 友元

友元的目的是让一个函数或类访问另一个类中的私有成员

3.4.1全局函数做友元

在类中定义全局函数并在前加上friend

class person {
    friend void goodway(person build);
public:
    string building;
private:
    string address;
};
void goodway(person build) {
    cout <<"成功访问" << build.address << endl;
}

3.4.2 类做友元

class Building;
class goodway {
public:
    goodway();
    void visit();//参观函数访问Building中的属性
    Building* building;
};
class Building{
    friend class goodway;//使得class可以访问building中的private成员
public:
    Building();
public:
    string m_sitroom;
private:
    string m_redroom;
};
Building::Building() {
    m_sitroom = "客厅";
    m_redroom = "卧室";
}
goodway::goodway() {
    building = new Building;
}
void goodway::visit() {
    cout << building->m_sitroom << endl;//调用building构造函数,给成员赋值
    cout << building->m_redroom << endl;
}

3.4.3 成员函数做友元

class goodway {
public:
    goodway();
    void visit();//让visit函数访问Building中的私有成员
    void visit2();//让visit2函数不可以访问Building私有成员
    Building* building;
};
class Building{
    friend void goodway::visit();
public:
    Building();
public:
    string m_sitroom;
private:
    string m_bedroom;
};

3.5运算符重载

3.5.1加号运算符重载

class person {
public:
    person operator+(person a) {
        person temp;
        temp.m_a = this->m_a + a.m_a;
        temp.m_b=this->m_b + a.m_b;
        return temp;
    }
    int m_a;
    int m_b;
};
void text01() {
    person p1;
    p1.m_a = 10;
    p1.m_b = 10;
    person p2;
    p2.m_a = 10;
    p2.m_b = 10;
    person p3 = p1 + p2;
    cout << p3.m_a << p3.m_b;
}
person operator+(person a,person b){
    person temp;
    temp.m_a = b.m_a + a.m_a;
    temp.m_b = b.m_b + a.m_b;
    return temp;
}

3.5.2 左移运算符重载

class person {
    friend ostream& operator<<(ostream& cout, person& p);
public:
    person() {
        m_a = 10;
        m_b = 20;
    }
private:
    int m_a;
    int m_b;
    //void operator<<(ostream& cout)
    //本质:p.operator<<(cout)-->p<<cout 不符合规范
};
ostream & operator<<(ostream &cout, person &p) {//本质:operator<<(cout,p)-->cout<<p;
    cout << p.m_a;
    cout << p.m_b;
    return cout;
}
void text01() {
    person p;
    cout << p <<"www" << endl;//链式编程思想,返回cout
}

3.5.3 递增/减运算符重载

class person {
    friend ostream& operator<<(ostream &cout, const person &p);
public:
    person(int a, int b) {
        m_a = a;
        m_b = b;
    }
    person & operator--() {
        m_a --;
        m_b--;
        return *this;
    }
    const  person operator--(int) {
        person temp = *this;
        m_a--;
        m_b--;
        return temp;
    }
private:
    int m_a;
    int m_b;
};
ostream & operator<<(ostream &cout, const person &p) {
    cout << p.m_a << endl;
    cout << p.m_b << endl;
    return cout;
}
void text01() {
    person p1(10, 20);
    cout << p1--;
    cout << p1;
    cout << --(--p1);
}

以引用为返回值的函数,可以通过值传递,可以通过引用传递。

以值为返回值的函数,通过引用传递时,必须在引用前加const,因为非const的引用不能绑定临时对象

3.5.4 赋值运算符重载

c++编译器给一个类添加四个函数:构造,析构,拷贝构造,赋值运算符 operator=对属性值拷贝

class person {
public:
    person(int age) {
        m_age=new int(age);
    }
    person & operator=(person &p) {
        //先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
        if (m_age == NULL) {
            delete m_age;
            m_age = NULL;
        }
        m_age = new int(*p.m_age);
        return *this;
    }
    ~person(){
        if (m_age != NULL) {
            delete m_age;
            m_age = NULL;
        }
        cout << "析构函数的调用" << endl;
    }
    int *m_age;
};
void text02() {
    person p2(10);
    person p3(29);
    person p4(39);
    p2 = p3 = p4;
    cout << *p2.m_age << *p3.m_age << *p4.m_age << endl;
}

编译器默认提供的赋值运算符是m_age=p.age的浅拷贝,在释放内存时会重复释放。

3.5.5 关系运算符重载

让两个自定义对象进行对比

class person {
public:
    person(string name, int age) {
        m_name = name;
        m_age = age;
    }
    bool operator==(person &p) {
        if (this->m_name == p.m_name && this->m_age == p.m_age) {
            return true;
        }
        return false;
    }
    string m_name;
    int m_age;
};

3.5.6 函数调用运算符重载

仿函数

class person {
public:
    //仿函数,重载小括号,形式不唯一
    int operator()(int a,int b) {
        return a + b;
    }
};
void text1() {
    person p1;
    int ret = p1(10, 20);
    cout << ret << endl;
    //匿名函数对象,用完释放
    cout << person()(10, 20);
}

3.6 继承

定义类时,下级成员会有上级成员的一些共性以及自己的特性

可以用继承来减少重复代码

3.6.1 继承的基本语法

class 子类 :继承方式 父亲

3.6.2 继承方式

不管哪种继承方式,都不能访问私有成员

  • 公共继承:父类中公共权限成员和保护权限成员到子类中依然相同
  • 保护继承:父类中公共权限成员和保护权限成员到子类中成为保护权限
  • 私有继承:父类中公共权限成员和保护权限成员到子类中成为私有权限

3.6.3 继承中的对象模型

父类中所有非静态成员属性都会被子类继承下去,父类中私有属性被编译器隐藏,所以不能访问

利用开发人员命令提示工具查看对象模型

跳转盘符 D: 跳转文件路径 cd

查看命名:dir

cl /d1 reportSingleClassLayoutson .\text1.cpp

3.6.4 继承中构造和析构顺序

先构造父类,再构造子类

析构与构造顺序相反

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

class base {
public:
    base() {
        m_a = 100;
    }
    void func() {
        cout << "base" << endl;
    }
    void func(int a) {
        cout << "base1" << endl;
    }
    int m_a;
};
class son : public base {
public:
    son() {
        m_a = 200;
    }
    void func() {
        cout << "son" << endl;
    }
    int m_a;
};
void texy01() {
    son s1;
    cout << s1.m_a;
    cout << s1.base::m_a;
}
void text02() {
    son s2;
    s2.func();
    //如果子类中函数名与父类相同,则会隐藏所有父类同名函数,如果要调用需要加作用域
    s2.base::func(100);
}

3.6.6 继承同名静态成员处理

静态成员有两种访问方式

void text01() {
    son s1;
    cout << s1.m_a;
    cout << s1.base::m_a;
    //通过类名的方式进行访问
    cout << son::m_a << endl;
    cout << son::base::m_a << endl;
}

3.6.7 菱形继承

两个类继承同一个类

有一个类同时继承这两个类

image-20250627183808576

class animal{//虚基类
public:
    int m_a;
};
class sheep:virtual public animal{};//虚继承
class tuo:virtual public animal{};
class yt:public sheep,public tuo{};
void text01() {
    yt s1;
    s1.sheep::m_a = 18;
    s1.tuo::m_a = 28;
    cout << s1.sheep::m_a << endl;
    cout << s1.tuo::m_a << endl;//输出28
}

虚继承只有一份数据

3.7 多态

3.7.1 基本概念

  • 静态多态:函数重载和运算符重载,复用函数名
  • 动态多态:派生类和虚函数实现运行多态

静态多态和动态多态的区别:

  • 静态多态分函数地址早绑定–编译阶段确定函数地址
  • 动态多态的函数地址晚绑定–运行阶段确定函数地址
class animal {
public:
//虚函数
    virtual void speak() {
        cout << "动物在说话" << endl;
    }
};
class cat :public animal {
//重写:函数返回值类型,函数名,参数列表完全相同
    public:
        void speak() {
            cout << "小猫在说话" << endl;
        }
};
class dog:public animal {
    void speak() {
        cout << "小狗在说话" << endl;
    }
};
//地址早绑定 在编译阶段确定函数地址
//如果想执行猫说话,地址晚执行
//动态多态满足条件:
//1.有继承关系
//2.子类重写父类中的虚函数
void dospeak(animal& manimal) {
    manimal.speak();
}
void text01() {
    cat mcat;
    dospeak(mcat);
    dog mdog;
    dospeak(mdog);
}

vfptr—-虚函数指针(指向虚函数表,表内部记录虚函数的地址 Animal&animal)

子类重写时,指向子类的虚函数表

3.7.2 案例:计算器(普通和多态)


class calculator {
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 text01() {
    calculator c;
    c.m_num1 = 10;
    c.m_num2 = 10;
    cout << c.m_num1 << "+" << c.m_num2 << "=" << c.getresult("+") << endl;
}
//利用多态实现计算器
//组织结构清晰
//可读性强
//前期和后期拓展以及维护性高
class basscalculator {
public:
    virtual int getresult() {
        return 0;
    }
    int m_num1;
    int m_num2;
};
//加法计算器
class jia :public basscalculator {
public:
    int getresult() {
        return m_num1 + m_num2;
    }
};
//乘法计算器
class cheng :public basscalculator {
public:
    int getresult() {
        return m_num1 * m_num2;
    }
};
void text02() {
    basscalculator* p = new jia;
    p->m_num1 = 10;
    p->m_num2 = 10;
    cout << p->getresult() << endl;
    p = new cheng;
    p->m_num1 = 10;
    p->m_num2 = 10;
    cout << p->getresult() << endl;
}

3.7.3 纯虚函数和抽象类

virtual 返回值类型 函数名 (参数列表)=0

3.7.4 多态案例:制作饮品

class drink {
public:
    virtual void boil() = 0;
    virtual void brew() = 0;
    virtual void pour() = 0;
    virtual void fuzhu() = 0;
    void makedrink() {
        boil();
        brew();
        pour();
        fuzhu();
    }
};
class coffee :public drink {
public:
    virtual void boil() {
        cout << "农夫山泉" << endl;
    }
    virtual void brew() {
        cout << "冲泡" << endl;
    }
    virtual void pour() {
        cout << "倒入杯中" << endl;
    }
    virtual void fuzhu() {
        cout << "加入糖和牛奶" << endl;
    }
};
class cha :public drink {
public:
    virtual void boil() {
        cout << "农夫山泉" << endl;
    }
    virtual void brew() {
        cout << "冲泡" << endl;
    }
    virtual void pour() {
        cout << "倒入杯中" << endl;
    }
    virtual void fuzhu() {
        cout << "加入枸杞" << endl;
    }
};
void dowork(drink* abs) {
    abs->makedrink();
}
void text02() {
    dowork(new coffee);
}

3.7.5 虚析构和纯虚析构

多态中如果子类中有属性开辟到堆区,那么父类指针无法释放

虚析构和纯虚析构解决了这个问题

class animal {
public:
    animal() {
        cout << "animal构造函数的调用" << endl;
    }
    //解决父类指针释放子类对象不干净的问题
    //virtual ~animal() {
        //cout << "aniaml析构函数的调用" << endl;
    //}
    //有纯虚析构这个类成为抽象类
    virtual ~animal() = 0;
    virtual void speak() = 0;

};
//需要声明也需要实现
animal::~animal() {
    cout << "纯虚析构函数的调用" << endl;
}
class cat :public animal {
public:
    cat(string name) {
        cout << "cat构造函数的调用" << endl;
        m_name = new string(name);
    }
    ~cat() {
        if (m_name != NULL) {
            delete m_name;
            cout << "cat析构函数的调用" << endl;
            m_name = NULL;
        }
    }
    virtual void speak() {
        cout <<*m_name<< "小猫在说话" << endl;
    }
    string* m_name;
};
void text01() {
    animal* p = new cat("tom");
    p->speak();
    //父类指针在析构时候不会调用子类析构,会导致堆区的内存无法释放
    delete p;
}

3.7.6 电脑组装具体实现

class cpu {
public:
    virtual void carculate() = 0;
    virtual ~cpu() {

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

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

    }
};
class internet :public cpu {
public:
    void carculate() {
        cout << "internet的cpu开始计算了" << endl;
    }
    ~internet() {

    }
};
class internet1 :public xianka {
public:
    void display() {
        cout << "internet的xianka开始运行了" << endl;
    }
};
class internet2 :public memory {
public:
    void storage(){
        cout << "internet的memory开始存储了" << endl;
    }
};
class lenovo :public cpu {
public:
    void carculate() {
        cout << "lenovo的cpu开始计算了" << endl;
    }

};
class lenovo1 :public xianka {
public:
    void display() {
        cout << "lenovo的xianka开始运行了" << endl;
    }
};
class lenovo2 :public memory {
public:
    void storage() {
        cout << "lenovo的memory开始存储了" << endl;
    }
};
class computer {
public:
    computer(cpu* CPU, xianka* XK, memory* MM) {
        mcpu = CPU;
        myxianka = XK;
        mymemory = MM;
    }
    void work() {
        mcpu->carculate();
        myxianka->display();
        mymemory->storage();
    }
    ~computer() {
        if (mcpu != NULL) {
            delete mcpu;
            mcpu = NULL;
        }
        if (myxianka != NULL) {
            delete myxianka;
            myxianka = NULL;
        }
        if (mymemory != NULL) {
            delete mymemory;
            mymemory = NULL;
        }
    }
private:
    cpu* mcpu;
    xianka* myxianka;
    memory* mymemory;
};
void text01() {
    cpu* a = new internet;
    xianka* b = new internet1;
    memory* c = new internet2;
    computer* computer1 = new computer(a, b, c);
    computer1->work();
    delete computer1;
    computer* computer2 = new computer(new internet, new lenovo1, new lenovo2);
    computer2->work();
    delete computer2;

}

4.文件操作

头文件

文本文件:文件以文本的ASCII码存储

二进制文件:文件以二进制形式存储,用户一般不能直接读懂

操作文件三大类:

1.ofstream:写操作

2.ifstream:读操作

3.fstream:读写操作

4.1文本文件

4.1.1 写文件

1.头文件

2.创建流对象

ofstream ofs;

3.打开文件

ofs.open(“文件路径”,打开方式)

4.写数据

ofs<<“写入的数据”;

5.关闭文件

ofs.close()

打开方式

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

如果打开方式要配合使用,利用|操作符

void text01() {
    ofstream ofs;
    ofs.open("test.txt", ios::out);
    ofs << "姓名:张三" << endl;
    ofs << "年龄:10" << endl;
    ofs << "性别:男" << endl;
    ofs.close();
}

4.1.2 读文件

1.头文件

2.创建流对象

ifstream ifs;

3.打开文件

ifs.open(“文件路径”,打开方式)

4.读数据

四种方式读取

5.关闭文件

ifs.close()

void text01() {
    //创建流对象
    ifstream ifs;
    //打开文件,并且判断是否打开成功
    ifs.open("test.txt", ios::in);
    if (!ifs.is_open()) {
        cout << "文件打开失败" << endl;
        return;
    }
    //第一种
    //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;
    }

    ifs.close();
}

4.2 二进制文件

打开方式 ios::binary

4.2.1 写文件

通过write函数,以二进制方式写数据

class person {
public:
    char m_name[64];
    int m_age;
};
void text01() {
    //包含头文件
    //创建流对象
    ofstream ofs;
    //打开文件
    ofs.open("text.txt", ios::out | ios::binary);
    //写文件
    person p = {"张三",19};
    ofs.write((const char*)&p, sizeof(person));
    ofs.close();
}

4.2.2 读文件

public:
    char name[64];
    int m_age;
};
void text01() {
    ifstream ifs;
    ifs.open("text.txt", ios::in|ios::binary);
    if (!ifs.is_open()) {
        cout << "文件打开失败" << endl;
        return;
    }
    person p;
    ifs.read((char*)&p, sizeof(person));
    cout << p.name << p.m_age << endl;
    ifs.close();
}

相关条目

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注