运算符重载-输入输出-左移运算符

05-2-1 运算符重载-输入输出-左移运算符

左移运算符重载的作用:让结构体或者类可以直接完成左移运算符,无需将数据单独从结构体或者类拿出来。常见的需要用到左移运算符(<<)的场景是:使用cout输出。

完成左移运算符重载有、且只有一种方法:

  • 在全局函数里面实现重载。

使用重载的时候,需要使用关键字operator。左移运算符重载的函数声明是(准确说是以cout为例):ostream& operator<<(ostream& cout, 结构体/类名称 变量);

为什么我们需要左移运算符重载:

  • 因为我们在使用类的时候,类如下:

    class test
    {
    public:
    int m_A;
    int m_B;
    };

    这时候实例化出一个对象,t1。我想要打印t1里面的成员属性的数据,需要访问t1才可以获取。比如说:

    cout << t1.m_A << t1.m_2 << endl;

    如果直接打印t1比如下面这样是会报错的。

    cout << t1 << endl;

    但是,我们可以使用左移运算符的重载来实现直接输出自定义的数据。

  • 为什么是重载左移运算符(<<)而不是其他的比如cout

    1. 因为如果我们在不进行重载左移运算符的使用输入如下的代码:

      cout << t1 << endl;

      会报错,但是报错的不是cout,而是t1前面的<<

      没有与这些操作数匹配的 "<<" 运算符

      所以我们需要重载的是左移运算符(<<)而不是其他的东西。

    2. cout不是运算符。

      我们在写 c++代码的时候,需要包含头文件:#include <iostream>。如果涉及到输入输出的,需要使用using namespace std;。这里面定义了cout的作用。

      cout是标准输出流下面的功能,而不是一个运算符。

如何进行左移运算符重载:

  1. 在全局函数里面实现重载。

    不同于四则运算的运算符重载,左移运算符重载只可以使用全局函数。

    如果在成员函数里面重载,本质上是一个类的对象调用一个函数,这时候还需要传入一个参数。比如:p.operator<<(cout),简化版本是:t1 << cout,不能实现cout << t1这样的重载,但是可以实现t1 << cout这样的重载。所以不用成员函数重载左移运算符的重载是因为不可以实现coutt1的左侧。

    cout是一个ostream(标准输出流)的函数,全局只可以有一个,所以传入的时候需要引用的方式传入。

    返回值也是一个cout,也还是全局只可以有一个,所以也需要引用的方式返回。事实上,在this指针([03-2 this指针](./03-2 this指针.md))中我们讲过一个链式编程思想: 比如coutcout使用左移运算符(<<)可以无限链接。比如:cout << "你好" << "我不好" << "啊?" << "我不好" << "听不见" << "n**l" << endl;无限链接下去。

    所以我们返回的时候,也必须要引用的方式返回,才可以让这个链一直链接下去。

    ostream& operator<<(ostream& cout, class test& p)
    {
    cout << "m_A = " << p.m_A << " m_B = " << p.m_B;
    return cout;
    }

    我们整体看一眼:

    #include 
    using namespace std;
    ostream& operator<<(ostream& cout, class test& p);
    class test
    {
    public:
    int m_A;
    int m_B;
    test()
    {
        m_A = 10;
        m_B = 20;
    }
    };
    int main()
    {
    class test t1;
    cout << t1 << endl;
    return 0;
    }
    ostream& operator<<(ostream& cout, class test& p)
    {
    cout << "m_A = " << p.m_A << " m_B = " << p.m_B;
    return cout;
    }

    运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)

    m_A = 10 m_B = 20
  2. 如何访问私有数据

    但我们使用类的时候,很多时候是采用私有权限(private),这时候,如果我们重载了左移运算符则无法成功读取。比如说这种情况:

    #include 
    using namespace std;
    ostream& operator<<(ostream& cout, class test& p);
    class test
    {
    private:
    int m_A;
    int m_B;
    public:
    test()
    {
        m_A = 10;
        m_B = 20;
    }
    };
    int main()
    {
    class test t1;
    cout << t1 << endl;
    return 0;
    }
    ostream& operator<<(ostream& cout, class test& p)
    {
    //cout << "m_A = " << p.m_A << " m_B = " << p.m_B;
    return cout;
    }

    这时候,函数operator<<或者说左移运算符(<<)重载中会报错。这是因为,对象中的m_Am_B成员属性是一个私有的(private)。

    如果我们希望能够成功打印数据,有两种方法:

    1. 使用友元(friend

      被友元标记的函数可以直接访问私有的数据(private),其语法是在类中开头使用friend关键字加上函数的声明。实际操作如下:

      #include 
      using namespace std;
      ostream& operator<<(ostream& cout, class test& p);
      class test
      {
      friend ostream& operator<<(ostream& cout, class test& p);
      private:
      int m_A;
      int m_B;
      public:
      test()
      {
          m_A = 10;
          m_B = 20;
      }
      };
      int main()
      {
      class test t1;
      cout << t1 << endl;
      return 0;
      }
      ostream& operator<<(ostream& cout, class test& p)
      {
      cout << "m_A = " << p.m_A << " m_B = " << p.m_B;
      return cout;
      }

      比如上面的例子中friend ostream& operator<<(ostream& cout, class test& p);,就是设置函数operator<<为类test的友元。

    2. 在公共权限(public)下提供接口用于读取数据

      代码如下:

      #include 
      using namespace std;
      ostream& operator<<(ostream& cout, class test& p);
      class test
      {
      private:
      int m_A;
      int m_B;
      public:
      test()
      {
          m_A = 10;
          m_B = 20;
      }
      int Getm_A()
      {
          return m_A;
      }
      int Getm_B()
      {
          return m_B;
      }
      };
      int main()
      {
      class test t1;
      cout << t1 << endl;
      return 0;
      }
      ostream& operator<<(ostream& cout, class test& p)
      {
      cout << "m_A = " << p.Getm_A() << " m_B = " << p.Getm_B();
      return cout;
      }

      当然,在使用公共接口获取数据的时候需要注意,重载函数中需要以函数的方式获取属性的数据值。

  • 注意:
    1. 完成左移运算符重载只有一种方法:在全局函数里面实现重载。其函数声明是(以cout为例):ostream& operator<<(ostream& cout, 结构体/类名称 变量);
    2. cout是一个标准输出流(ostream)的函数,有,且只有一个,所以必须使用引用的方式传入函数。
  • 提示:
    1. 为了实现链式编程,返回值也是引用方式返回的cout
    2. 如果类里面的数据是私有(private),可以使用友元(friend)将左移运算符重载的函数设置为友元,这样可以直接访问。当然,也可以提供公共权限(public)下的接口。
    3. 在开发中,如果在写函数的时候,不知道要返回什么的话可以先使用void声明返回值,后续发现要返回的时候再修改也不迟。
文章「运算符重载-输入输出-左移运算符」,由本站用户「Admin」发布。文章仅代表Admin观点,不代表本站立场。
页面网页地址「https://xiaozhiyuqwq.top/p/904」。
如您对文章及其附件提出版权主张,或进行引用转载等,请查看我们的【版权声明】
无评论:-)

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇