左移运算符重载:可以打印输出自定义数据类型

为了输出重载,我们先看看现有的输出函数。输出类型为std下的ostream类型的引用。

标准输出流(全局只能有一个)。

返回值类型为ostream,函数名称operator<<,输入参数为我们自定义类型。

仿照加号运算符重载,我们先试试成员函数。

ostream& operator<<(Person& p) {}

利用成员函数重载 左移运算符调用情形:p.operator<<(p)。先有一个对象调用函数,然后还要输入一个对象。这不是我们期望的:cout << p;的情景。简写方式只能通过p << cout方式调用。

我们把cout也加入进去:返回一个ostream类型,这样可以形成链式编程。

ostream& operator<<(ostream& cout)
{cout << "这个对象的m_A的值为:" << this->m_A << "这个对象的m_B的值为:" << this->m_B;return cout;
}

这样成员函数的输入是一个ostream流的引用,输出也是一个ostream流的引用,可以满足链式需求。

调用情况:

Person p(11, 22);
// 直接调用:
//p.operator<<(cout) << endl;
// 返回类型:调用方式一。
//ostream& out = p.operator<<(cout) << endl;
// 支持这种调用。
//p << cout << endl;

输出:

这个对象的m_A的值为:11。 这个对象的m_B的值为:22

代码:

#include<iostream>
using namespace std;
#include<string>class Person
{
public:Person(int a, int b){this->m_A = a;this->m_B = b;}ostream& operator<<(ostream& outStream){outStream << "这个对象的m_A的值为:" << this->m_A << "。 这个对象的m_B的值为:" << this->m_B;return outStream;}public:int m_A;int m_B;
};void test01()
{Person p(11, 22);// 直接调用://p.operator<<(cout) << endl;// 返回类型://ostream& out = p.operator<<(cout) << endl;// 支持这种调用。p << cout << endl;
}
int main()
{test01();system("pause");return 0;
}



调用方式是:p<< cout。方向反了,我们希望的场景是:cout << p;

利用成员函数实现这样的场景不行了。只能采用全局函数的形式。

一般不会利用成员函数重载左移运算符<< ,因为无法实现cout在左侧的情况。只能用全局函数来实现。

简写方式是cout << p;所以应该是cout在左,在前,p在右,在后。定义一个全局函数:

void operator<<(cout, Person p) {} // 本质:operator<<(cout, p)简化形式可以写成cout << p;

本质:operator(cout, p),可简化写为:cout << p;

上面我们查到cout的类型为ostream;然后为了保证cout的全局唯一性:我们输入cout的引用。

补充函数:

void operator<<(ostream& cout, Person p)  // 本质:operator<<(cout, p)简化形式可以写成cout << p;
{cout << "m_A = " << p.m_A << "; m_B = " << p.m_B;
}

此时可调用如下:

void test02()
{Person p(11, 22);operator<<(cout, p);//cout << p;
}

简化调用没问题。本质调用operator<< 也没问题。

但是cout支持链式编程,即可以在后面不断接<<,所以应该返回对于cout本体的引用

全局函数变更为:将局部变量名换成out也可以。

ostream& operator<<(ostream& out, Person p)  // 本质:operator<<(out, p)简化形式可以写成cout << p;
{out << "m_A = " << p.m_A << "; m_B = " << p.m_B;return out;
}

还剩最后一个问题:

在类内:一般我们把字段设置为私有private。这样在类外基于全局函数的运算符重载将无法访问到字段,所以整套的做法:要把全局函数的重载声明作为友元放在类内。

#include<iostream>
using namespace std;
#include<string>class Person
{friend ostream& operator<<(ostream& out, Person p);
public:Person(int a, int b){this->m_A = a;this->m_B = b;}//ostream& operator<<(ostream& outStream)//{//   outStream << "这个对象的m_A的值为:" << this->m_A << "。 这个对象的m_B的值为:" << this->m_B;//    return outStream;//}private:int m_A;int m_B;
};ostream& operator<<(ostream& cout, Person p)  // 本质:operator<<(cout, p)简化形式可以写成cout << p;
{cout << "m_A = " << p.m_A << "; m_B = " << p.m_B;return cout;
}void test02()
{Person p(11, 22);//operator<<(cout, p) << endl;cout << p << endl;}
void test01()
{Person p(11, 22);// 直接调用://p.operator<<(cout) << endl;// 返回类型://ostream& out = p.operator<<(cout) << endl;// 支持这种调用。//p << cout << endl;
}
int main()
{test02();cout;system("pause");return 0;
}

需要总结的几点:结合上一个案例加号运算符重载:发现

  • 运算符重载作为类内成员函数,在调用时是p1.operator+(p2)。可简写为p1+p2。或者p2+p1。
  • 运算符重载作为类外全局函数,在调用时是opearator(p1, p2)。可简写为p1+p2。后者p2+p1。
    • 也就是说必须类内成员函数输入参数有一个二元运算符中的一元,类外一元作为一元。
    • 类外全局函数输入参数是二元运算符中的两个元。
  • 加号无所谓方向要求。左移运算符因为有方向和顺序,所以无法用类内成员函数实现。在全局实现中也要注意参数顺序。
  • 链式编程返回本体引用。

C++类与对象笔记十二:运算符重载二:左移运算符重载相关推荐

  1. C++类与对象笔记十四:多态六:虚析构和纯虚析构

    多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用子类的析构代码. 即:父类指针无法调用子类实例对象内的析构函数.造成堆区内存泄漏. 解决方案:将父类中的析构函数改为虚析构或者纯虚析 ...

  2. Kotlin学习笔记 第二章 类与对象 第十二 十三节 对象表达式与对象声明 类型别名

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  3. Kotlin学习笔记 第二章 类与对象 第十四 十五节 委托 委托属性

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  4. C++_类和对象_C++运算符重载_左移运算符重载_链式编程_实现直接打印对象---C++语言工作笔记056

    然后我们再去看左移运算符,实际上就是那个<< 小于号 为什么要重载他呢?因为我们想实现一个功能,比如我仅仅是cout << p 就可以打印这个对象,现在肯定是不行对吧. 我们用 ...

  5. c++,运算符重载,左移运算符自增运算符。

    假设有类A,它的私有成员是一个整型变量a_ A a; 我们想要把它的私有成员直接用 cout<<a<<endl 输出的话要用到左移运算符的重载. 我们把<<运算符重 ...

  6. 运算符重载之左移运算符重载

    左移运算符重载 #include<iostream> using namespace std; class wood {friend ostream& operator<&l ...

  7. Kotlin学习笔记 第二章 类与对象 第十节 内部类嵌套类

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  8. PHP的类与对象-笔记

    对象的赋值: 手册中有如下一个例子,个人理解如下 $assigned = $instance; $reference =& $instance; $instance--->var = ' ...

  9. 【C++ 七】类和对象:封装、继承、多态、友元、运算符重载

    封装.继承.多态.对象的初始化和清理.C++对象模型和this指针.友元.运算符重载 文章目录 封装.继承.多态.对象的初始化和清理.C++对象模型和this指针.友元.运算符重载 前言 1 封装 1 ...

最新文章

  1. 2021-2027年中国智能马桶盖行业市场研究及前瞻分析报告
  2. Centos7上openVP-密钥登陆
  3. 《配置管理最佳实践》——2.10 建立构建过程
  4. IntelliJ IDEA 15发布
  5. bootstrap-select采坑
  6. Redux API之applyMiddleware
  7. 【机器学习】总结:线性回归求解中梯度下降法与最小二乘法的比较
  8. 栈应用:实现二进制转八进制、十进制、十六进制
  9. tcpip详解有必要看吗_车辆有必要安装“行车记录仪”吗?如何挑选看这里!
  10. 绘图之使用工作空间直接绘图
  11. 树莓派 4b 可执行文件 无法双击运行_树莓派01 - 树莓派系统安装
  12. 湖北随州:借大数据“慧眼”织密扶贫监督网
  13. 常数除以0的极限是什么_【高数总结求极限方法】百度作业帮
  14. 天气实况、天气预报、免费天气接口、空气质量各类天气数据、生活指数、气候数据雷达云图等值面...
  15. java hook api 实现封包截取_hook 封包 截取WSASend实例
  16. c0704 学生记录
  17. C/C++编程:std::move(将左值强制转换为右值)
  18. cocos2d编写android插件,[分享]Xposed插件dump Cocos2d-x应用的lua脚本
  19. 一个程序员的自白(认同迷失)
  20. 【黑盒测试】 正交排列法设计测试用例

热门文章

  1. 本地化社交问答网站Drumo瞄准亚洲和澳洲市场
  2. RNA 30. SCI文章中基于TCGA和GTEx数据挖掘神器(GEPIA2)
  3. Java 提取EXIF信息批量重命名
  4. 点赋网络:淘宝开店货源怎么选
  5. html 怎么让div卷角,css实现简约的纸张卷角效果
  6. Stave——让Fiddler拥有路径映射功能。
  7. 浏览器对象BOM对象有哪些?
  8. 排位赛三E. Word Processor
  9. java 中的 JUC
  10. Aria2 新手入门