转载:http://c.biancheng.net/view/2311.html

C++中,标准库本身已经对左移运算符<<和右移运算符>>分别进行了重载,使其能够用于不同数据的输入输出,但是输入输出的对象只能是 C++ 内置的数据类型(例如 bool、int、double 等)和标准库所包含的类类型(例如 string、complex、ofstream、ifstream 等)。

如果我们自己定义了一种新的数据类型,需要用输入输出运算符去处理,那么就必须对它们进行重载。本节以前面的 complex 类为例来演示输入输出运算符的重载。

其实 C++ 标准库已经提供了 complex 类,能够很好地支持复数运算,但是这里我们又自己定义了一个 complex 类,这样做仅仅是为了教学演示。

本节要达到的目标是让复数的输入输出和 int、float 等基本类型一样简单。假设 num1、num2 是复数,那么输出形式就是:

cout<<num1<<num2<<endl;

输入形式就是:

cin>>num1>>num2;

cout 是 ostream 类的对象,cin 是 istream 类的对象,要想达到这个目标,就必须以全局函数(友元函数)的形式重载<<>>,否则就要修改标准库中的类,这显然不是我们所期望的。

重载输入运算符>>

下面我们以全局函数的形式重载>>,使它能够读入两个 double 类型的数据,并分别赋值给复数的实部和虚部:

  1. istream & operator>>(istream &in, complex &A){
  2. in >> A.m_real >> A.m_imag;
  3. return in;
  4. }
istream & operator>>(istream &in, complex &A){
in >> A.m_real >> A.m_imag;
return in;
}

istream 表示输入流,cin 是 istream 类的对象,只不过这个对象是在标准库中定义的。之所以返回 istream 类对象的引用,是为了能够连续读取复数,让代码书写更加漂亮,例如:

complex c1, c2;
cin>>c1>>c2;

如果不返回引用,那就只能一个一个地读取了:

complex c1, c2;
cin>>c1;
cin>>c2;

另外,运算符重载函数中用到了 complex 类的 private 成员变量,必须在 complex 类中将该函数声明为友元函数:

friend istream & operator>>(istream & in , complex &a);

>>运算符可以按照下面的方式使用:

complex c;
cin>>c;

当输入1.45 2.34后,这两个小数就分别成为对象 c 的实部和虚部了。cin>> c;这一语句其实可以理解为:

operator<<(cin , c);

重载输出运算符<<

同样地,我们也可以模仿上面的形式对输出运算符>>进行重载,让它能够输出复数,请看下面的代码:

  1. ostream & operator<<(ostream &out, complex &A){
  2. out << A.m_real <<" + "<< A.m_imag <<" i ";
  3. return out;
  4. }
ostream & operator<<(ostream &out, complex &A){
out << A.m_real <<" + "<< A.m_imag <<" i ";
return out;
}

ostream 表示输出流,cout 是 ostream 类的对象。由于采用了引用的方式进行参数传递,并且也返回了对象的引用,所以重载后的运算符可以实现连续输出。

为了能够直接访问 complex 类的 private 成员变量,同样需要将该函数声明为 complex 类的友元函数:

friend ostream & operator<<(ostream &out, complex &A);

综合演示

结合输入输出运算符的重载,重新实现 complex 类:

  1. #include <iostream>
  2. using namespace std;
  3. class complex{
  4. public:
  5. complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ };
  6. public:
  7. friend complex operator+(const complex & A, const complex & B);
  8. friend complex operator-(const complex & A, const complex & B);
  9. friend complex operator*(const complex & A, const complex & B);
  10. friend complex operator/(const complex & A, const complex & B);
  11. friend istream & operator>>(istream & in, complex & A);
  12. friend ostream & operator<<(ostream & out, complex & A);
  13. private:
  14. double m_real; //实部
  15. double m_imag; //虚部
  16. };
  17. //重载加法运算符
  18. complex operator+(const complex & A, const complex &B){
  19. complex C;
  20. C.m_real = A.m_real + B.m_real;
  21. C.m_imag = A.m_imag + B.m_imag;
  22. return C;
  23. }
  24. //重载减法运算符
  25. complex operator-(const complex & A, const complex &B){
  26. complex C;
  27. C.m_real = A.m_real - B.m_real;
  28. C.m_imag = A.m_imag - B.m_imag;
  29. return C;
  30. }
  31. //重载乘法运算符
  32. complex operator*(const complex & A, const complex &B){
  33. complex C;
  34. C.m_real = A.m_real * B.m_real - A.m_imag * B.m_imag;
  35. C.m_imag = A.m_imag * B.m_real + A.m_real * B.m_imag;
  36. return C;
  37. }
  38. //重载除法运算符
  39. complex operator/(const complex & A, const complex & B){
  40. complex C;
  41. double square = A.m_real * A.m_real + A.m_imag * A.m_imag;
  42. C.m_real = (A.m_real * B.m_real + A.m_imag * B.m_imag)/square;
  43. C.m_imag = (A.m_imag * B.m_real - A.m_real * B.m_imag)/square;
  44. return C;
  45. }
  46. //重载输入运算符
  47. istream & operator>>(istream & in, complex & A){
  48. in >> A.m_real >> A.m_imag;
  49. return in;
  50. }
  51. //重载输出运算符
  52. ostream & operator<<(ostream & out, complex & A){
  53. out << A.m_real <<" + "<< A.m_imag <<" i ";;
  54. return out;
  55. }
  56. int main(){
  57. complex c1, c2, c3;
  58. cin>>c1>>c2;
  59. c3 = c1 + c2;
  60. cout<<"c1 + c2 = "<<c3<<endl;
  61. c3 = c1 - c2;
  62. cout<<"c1 - c2 = "<<c3<<endl;
  63. c3 = c1 * c2;
  64. cout<<"c1 * c2 = "<<c3<<endl;
  65. c3 = c1 / c2;
  66. cout<<"c1 / c2 = "<<c3<<endl;
  67. return 0;
  68. }
#include <iostream>
using namespace std; class complex{
public:
complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ };
public:
friend complex operator+(const complex & A, const complex & B);
friend complex operator-(const complex & A, const complex & B);
friend complex operator*(const complex & A, const complex & B);
friend complex operator/(const complex & A, const complex & B);
friend istream & operator>>(istream & in, complex & A);
friend ostream & operator<<(ostream & out, complex & A);
private:
double m_real; //实部
double m_imag; //虚部
}; //重载加法运算符
complex operator+(const complex & A, const complex &B){
complex C;
C.m_real = A.m_real + B.m_real;
C.m_imag = A.m_imag + B.m_imag;
return C;
} //重载减法运算符
complex operator-(const complex & A, const complex &B){
complex C;
C.m_real = A.m_real - B.m_real;
C.m_imag = A.m_imag - B.m_imag;
return C;
} //重载乘法运算符
complex operator*(const complex & A, const complex &B){
complex C;
C.m_real = A.m_real * B.m_real - A.m_imag * B.m_imag;
C.m_imag = A.m_imag * B.m_real + A.m_real * B.m_imag;
return C;
} //重载除法运算符
complex operator/(const complex & A, const complex & B){
complex C;
double square = A.m_real * A.m_real + A.m_imag * A.m_imag;
C.m_real = (A.m_real * B.m_real + A.m_imag * B.m_imag)/square;
C.m_imag = (A.m_imag * B.m_real - A.m_real * B.m_imag)/square;
return C;
} //重载输入运算符
istream & operator>>(istream & in, complex & A){
in >> A.m_real >> A.m_imag;
return in;
} //重载输出运算符
ostream & operator<<(ostream & out, complex & A){
out << A.m_real <<" + "<< A.m_imag <<" i ";;
return out;
} int main(){
complex c1, c2, c3;
cin>>c1>>c2; c3 = c1 + c2;
cout<<"c1 + c2 = "<<c3<<endl; c3 = c1 - c2;
cout<<"c1 - c2 = "<<c3<<endl; c3 = c1 * c2;
cout<<"c1 * c2 = "<<c3<<endl; c3 = c1 / c2;
cout<<"c1 / c2 = "<<c3<<endl; return 0;
}

运行结果:
2.4 3.6
4.8 1.7
c1 + c2 = 7.2 + 5.3 i
c1 - c2 = -2.4 + 1.9 i
c1 * c2 = 5.4 + 21.36 i
c1 / c2 = 0.942308 + 0.705128 i

C++重载>>和<<(输入和输出运算符)详解的更多相关文章

  1. .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]

    方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...

  2. PHP类和对象之重载

    PHP中的重载指的是动态的创建属性与方法,是通过魔术方法来实现的.属性的重载通过__set,__get,__isset,__unset来分别实现对不存在属性的赋值.读取.判断属性是否设置.销毁属性. ...

  3. C#基础回顾(二)—页面值传递、重载与重写、类与结构体、装箱与拆箱

    一.前言 -孤独的路上有梦想作伴,乘风破浪- 二.页面值传递 (1)C#各页面之间可以进行数据的交换和传递,页面之间可根据获取的数据,进行各自的操作(跳转.计算等操作).为了实现多种方式的数据传递,C ...

  4. new/delete重载

    在c++中,有时我们需要在运行阶段为一个变量分配未命名的内存,并使用指针来访问它,这里就可以用到new关键字.另外需要指出的是,new分配的内存块通常与常规变量分配的内存块不同,常规变量的值都储存在被 ...

  5. java重载与覆写

    很多同学对于overload和override傻傻分不清楚,建议不要死记硬背概念性的知识,要理解着去记忆. 先给出我的定义: overload(重载):在同一类或者有着继承关系的类中,一组名称相同,参 ...

  6. 【C++】多态性(函数重载与虚函数)

    多态性就是同一符号或名字在不同情况下具有不同解释的现象.多态性有两种表现形式: 编译时多态性:同一对象收到相同的消息却产生不同的函数调用,一般通过函数重载来实现,在编译时就实现了绑定,属于静态绑定. ...

  7. C++ 运算符重载时,将运算符两边对象交换问题.

    在C++进行运算符重载时, 一般来讲,运算符两边的对象的顺序是不能交换的. 比如下面的例子: #include <iostream> using namespace std; class ...

  8. C++重载new和delete运算符

    内存管理运算符 new.new[].delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内 ...

  9. Java学习笔记之方法重载

    被重载的方法必须具有不同的参数列表.不能基于不同修饰符或返回值类型来重载方法. package welcome; public class TestMethodOverloading { public ...

  10. Qt 5.0+ 中 connect 新语法与重载函数不兼容问题的解决方法,以及个人看法

    Qt 5.0+ 版本提供了 connect 的新语法,相比之前的语法新语法可以提供编译期检查,使用也更方便.可是使用过程中发现一个小问题——当某个 signal 和成员函数是重载关系的时候,qmake ...

随机推荐

  1. python执行gradle脚本

    import os import shutil import subprocess #拷贝文件 def copyFile(srcFile, dstFile): #检查源文件是否存在 if not os ...

  2. Guava Retrying

    目录 依赖 使用demo RetryerBuilder 实现callable接口 调用 git 参考 依赖 <dependency> <groupId>com.github.r ...

  3. Google Kick Start 2020 Round B T1-3

    这场题目除了最后一题稍微难了点,其他都是1眼题. T1 Bike Tour 没啥好说的,一个循环解决. T2 Bus Routes 没啥好说的,从第\(n\)的车站开始贪心取最晚的. T3 Robot ...

  4. Zabbix Agent升级

      最近对Zabbix Server进行了升级,所以陆陆续续对Zabbix Agent也做了升级,下面是这几天工作的一个小结,鉴于经验有限和认知有限等各方面因素,下文很难面面俱到,如有疏漏或不足之处, ...

  5. Vue文件模板

    <template> <div> </div> </template> <script> export default { } </s ...

  6. 20190926-01Redis五大数据类型之List 000 027

  7. C#通过Com串口进行Barcode Printer

    前言 工作中有遇到Barcode打印的需求,最开始是通过打印机型号找到对应的打印机,再进行操作,但是需要匹配的打印机型号太多,而且不定,所以处理起来太过麻烦. 后面通过找到通过串口找到打印机,直接传输 ...

  8. Spring Boot入门,源码解析

    目录 1.Spring Boot简介 2.微服务 3.Spring Boot HelloWorld 3.1 创建一个Maven工程 3.2 导入依赖Spring Boot相关的依赖 3.3 编写一个主 ...

  9. yum安装软件包提示Error Downloading Packages解决方法

    在执行yum upgrade时报错 解决方法: 方法一: 1.清理本地yum缓存 执行:yum clean all 2.查看软件包列表 执行:yum list 注意:如果查询不到软件包列表,查看yum ...

  10. oracle之三RMAN概述

    RMAN概述 6.1 rman的定义和功能: 1) Recovery Manager 2)建立备份和恢复的server process,在oracle server上做备份和恢复 3)rman 备份d ...