• C++流插入和流提取的重载!


    C++作为C语言的衍生,其弥补了C语言中的很多不足,也对C语言进行了一定的优化!今日就来讲解一下C++中输入/出流相关的知识!以及对输入/出的重载!,希望读完本篇文章,能让读者们对C++中输入/出流有更深一步的认识!


    C++流插入/提取的引出

    不知道小伙伴们是否注意到,C++中内置类型能直接被iostream流识别,但是自定义类型不能被识别!而且在C++中对一个内置类型输入/出时,不用再像C语言那样,规定输入/出格式!而是编译器自动识别输入输出的格式,这真的是编译器真的自动识别的么?实际上不是的!编译器只是对这些运算符进行重载,然后再对类型匹配的形参进行函数重载匹配正确的函数,那么是否能对自定义类型进行输出/入呢?答案是肯定的,这时就用到了C++中流输出/出的运算符重载


    C++流插入/提取的重载

    那么既然能进行运算符重载,那么如果想要一次输入/输出一个类,应该怎么搞呢?对于C++而言,只需要对流插入和流提取进行一下运算符重载就可以实现一次性输入/输出整个类想要输出的成员!下面我就来给大家实现一下对流插入/提取进行重载来实现对类对象的输入/出!

    流输出的重载

    通过对流输出的重载来实现对类对象的整体输出,代码如下:

    1. class Data
    2. {
    3. //在类中声明友元函数即可在外部进行访问!!!
    4. //对于日期类的引用必须要加const进行修饰,不能改变原来的日期类!!!
    5. friend ostream& operator<<(ostream& out, const Data& a);
    6. public:
    7. //构造函数!
    8. Data(int year,int month,int day)
    9. {
    10. cout << "Data()" << endl;
    11. _year = year;
    12. _month = month;
    13. _day = day;
    14. }
    15. //析构函数!!
    16. ~Data()
    17. {
    18. ;
    19. }
    20. private:
    21. int _year;
    22. int _month;
    23. int _day;
    24. };
    25. //void operator<<(ostream& out, const Data& a)
    26. //{
    27. // //利用友元函数来对类中的私有成员进行访问!!
    28. // out << a._year << "/" << a._month << "/" << a._day << endl;
    29. //}
    30. int main()
    31. {
    32. Data d1(2023,9,21);
    33. cout << d1;
    34. }

    我们还是以简单的日期类来举例子,如果我们想要对类中的若干成员进行输出时,那么此时我们需要对流输出进行运算符重载!

    但是需要注意的是:只能在类外进行声明定义,不能在类内定义,因为在类内定义时,函数会自动省略一个this指针,又因为<<操作符是基于两个变量的,而省略的第一个变量是this指针,若在类内定义时,结果是:this.data<因为输出流是变量流出到控制台,而现在导致的是控制台输出到变量内!显然与原来的顺序构成相反了,所以不能在类内进行定义!

    注:对第二个参数日期类的引用时,尽量加上const修饰,因为当对日期类输出时,日期类是不会改变的!所以加上const是一种较安全的做法!!


    那么只能在类外定义运算符重载!那么在类外定义运算符重载的时候,需要注意的是:因为在类外,所以对类内的private 成员不能进行访问!!那么该如何解决呢?

    1.用友元声明进行声明解决!

    2.直接将类中的成员全部声明为public类型成员!

    注:能尽量不使用友元声明就不使用,因为使用了友元声明,会破坏了类的封装性!还有可能对数据的保护减弱!

    有些眼尖的小伙伴发现,若是想输出多组类!那么返回值类型为void 岂不是行不通了么,对的,这时我们只需要将返回值类型变为(ostream&),即对输出流的引用,就可以实现多组的输出!代码如下:

    此时,对流输出的重载已经完成了!


    流输入的重载

    既然实现了流输出的重载,那么流输入的重载一定也能实现!那么该如何实现呢?是否和流输出的操作一样呢?

    其实,流输入的重载与流输出的重载没有什么区别!但是有一点的区别就是日期类的引用不能加上const,因为一旦加上了const编译器就会报错!

    会报错没有与操作数匹配的运算符!因为进行输入时,本质上就是对一个变量进行修改,而加上了const就具有了常属性,所以编译器会报错!

    流输入的代码如下:

    1. class Data
    2. {
    3. //在类中声明友元函数即可在外部进行访问!!!
    4. //进行流输入的时候一定不能加上const,一旦加上const编译器就会报错!!
    5. friend istream& operator<<(ostream& in, Data& a);
    6. public:
    7. //构造函数!
    8. Data(int year,int month,int day)
    9. {
    10. cout << "Data()" << endl;
    11. _year = year;
    12. _month = month;
    13. _day = day;
    14. }
    15. //析构函数!!
    16. ~Data()
    17. {
    18. ;
    19. }
    20. private:
    21. int _year;
    22. int _month;
    23. int _day;
    24. };
    25. //void operator>>(istream& in, Data& a)
    26. //{
    27. // //利用友元函数来对类中的私有成员进行访问!!
    28. // in>>a._year>> a._month>>a._day;
    29. //}
    30. int main()
    31. {
    32. Data d1(2023,9,21);
    33. cin >> d1;
    34. }

    通过对输出流进行简单的修改即可以完成对输入流运算符的重载!


    输入/出流重载完整代码

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include<iostream>
    3. using namespace std;
    4. //利用函数重载和输入/出流来实现运算符重载!!用来打印类的成员!!
    5. //注意:必须在全局中进行运算符重载!不能在类内定义运算符重载!
    6. //因为类中的运算符重载其省略了第一个参数this指针,但是“<<”又是双操作数操作符!
    7. //有着严格的顺序要求!!所以只能在全局定义运算符重载!!
    8. class Data
    9. {
    10. //在类中声明友元函数即可在外部进行访问!!!
    11. friend ostream& operator<<(ostream& out, const Data& a);
    12. friend istream& operator>>(istream& in, Data& a);
    13. public:
    14. //构造函数!
    15. Data(int year,int month,int day)
    16. {
    17. cout << "Data()" << endl;
    18. _year = year;
    19. _month = month;
    20. _day = day;
    21. }
    22. //析构函数!!
    23. ~Data()
    24. {
    25. ;
    26. }
    27. private:
    28. int _year;
    29. int _month;
    30. int _day;
    31. };
    32. //void operator<<(ostream& out, const Data& a)
    33. //{
    34. // //利用友元函数来对类中的私有成员进行访问!!
    35. // out << a._year << "/" << a._month << "/" << a._day << endl;
    36. //}
    37. //输出流运算符重载
    38. ostream& operator<<(ostream& out, const Data& a)
    39. {
    40. //可以利用友元函数来对类中的私有成员进行访问!!
    41. out << a._year << "/" << a._month << "/" << a._day << endl;
    42. return out;
    43. }
    44. //输入流运算符重载!
    45. //当进行输入流重载函数的时候,对类不能加上const修饰!因为一旦加上const修饰类,那么类就无法进行输入!
    46. istream& operator>>(istream& in, Data& a)
    47. {
    48. //利用友元函数来对类中的私有成员进行访问!!
    49. in >> a._year >> a._month >> a._day;
    50. return in;
    51. }
    52. int main()
    53. {
    54. Data d1(2023,9,21);
    55. Data d2(2023,9,22);
    56. Data d3(2023,9,23);
    57. cout << d1<<d2<<d3;
    58. cin>>d1;
    59. cout << d1;
    60. }

    好了,今日的输入/出流运算符重载结束了,希望读者们读完文章会有一定的收获,若有错误!也希望读者们提出,笔者必定积极改正!

  • 相关阅读:
    "嫦娥奔月",难道古人早已看透一切?
    Sora - 探索AI视频模型的无限可能
    洛谷-线段覆盖-(区间排序问题总结)
    详谈负载均衡(微服务架构下的高可用挑战)
    ​Bigemap软件在农业行业中的应用
    阶段性测试完成后,你进行缺陷分析了么?
    面了三十个人,说说真实感受
    基于函数计算自定义运行时快速部署一个 springboot 项目
    痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(2.3)- 串行NOR Flash下载算法(J-Link工具篇)
    Notepad++ 通过HexEditor插件查看.hprof文件、heap dump文件的堆转储数据
  • 原文地址:https://blog.csdn.net/weixin_71276184/article/details/133150144