运算符重载相信大家都不陌生。运算符函数通常分为两种形式:一类是在类中定义的运算符成员函数,称之为类成员运算符;另一种在类之外定义的运算符重载,通常以该类的友元形式,称之为友元运算符。

1、重载输入输出运算符的形式。常见的形式如下:

类型中声明友元函数(友元函数必须在类中声明)

class Complex{  public:Complex( double r=0, double i=0):real(r),imag(i){ };friend ostream & operator<<( ostream & os,const Complex & c);friend istream & operator>>( istream & is,Complex & c);private:double real,imag;
};

具体的定义:

ostream & operator<<( ostream & os,const Complex & c){os << c.real << "+" << c.imag << "i"; //以"a+bi"的形式输出return os;
}
istream & operator>>( istream & is,Complex & c){string s;is >> s;  //将"a+bi"作为字符串读入, "a+bi" 中间不能有空格int pos = s.find("+",0);string sTmp = s.substr(0,pos); //分离出代表实部的字符串c.real = atof(sTmp.c_str());//atof库函数能将const char*指针指向的内容转换成 floatsTmp = s.substr(pos+1, s.length()-pos-2);   //分离出代表虚部的字符串c.imag = atof(sTmp.c_str());return is;
}

2、重载输入输出运算符函数的参数。

答:由以上形式可以知道是两个参数。

(1)第一个参数是非常量的(输出/输入)流的引用。

之所以ostream是非常量的原因是:向流写入内容会改变流的状态。必须是引用的原因是:不用引用的话就是按值传递,而iostream(ostream/istream)规定是不允许拷贝器副本的,所以必须要传引用。对于重载输入运算符它的第一个参数应该也是这个道理。(注:cout 是 ostream 类的对象。ostream 类和 cout 都是在头文件 <iostream> 中声明的。)

(2)第二个参数输入和输出运算符的重载则不同:

输出运算符重载:对于重载输出运算符而言第二个参数是一个const的引用,该常量就是我们想要打印的类类型。采用引用的原因是我们希望避免复制实参;而之所以是常量的原因是通常情况下我们只是打印该形参默认不允许修改对象的内容。

输入运算符重载:对于重载输入运算符而言第二个参数必须是一个非const的引用。原因是它要存储我们读取到的数据,所以这个形参一定是能修改的才行。

3、为什么看到的重载输入输出运算符都选择友元函数的形式,而加/减/乘/除等符号的重载亦可采用成员函数形式?

通常重载输入输出(运算符)时必须是非成员函数重载,主要是为了与iostream标准库兼容。

为了与标准IO库一致,重载后的符号的左侧应该是流的引用,右侧是对象的引用。(如,cout<<"hello!";或cin>>tmp;等。)

但是如果重载为类的成员函数的话,运算符左侧是对象的引用,右侧是流的引用。(ps:事实的确如此,回想一下成员函数的重载都是对象在前运算符号在后。)也就是说其形式为:

Sales_data  data;data  <<  cout;//如果operator<<是Sales_data的成员。

显然这就与标准的IO库不一致了。所以为了与iostream标准库兼容,输入输出运算符尽量不重载为类的成员函数,大多重载为类的友元函数或普通函数。

4、如果强行的选择成类的成员函数的形式行不行?

根据前面说的应该也能看出来,强行的话肯定是行的。只不过看着太别扭了。

老实说这样用的几乎不会用到,如果感兴趣的话可以看看 这个。

5、最后放一个String的类,功能并不是很完全,但包括是常用的重载实现。

#include <iostream>
#include <string.h>
using namespace std;class String{public:String(const char* str=NULL);//普通构造函数String(const String &other);//拷贝构造函数~String();    //析构函数String & operator=(const String &other);//赋值函数String & operator+(const String &other);//字符串连接//重载输出运算符(友元重载,所以声明和定义处都和成员函数重载略有区别)friend    ostream & operator<<(ostream &os,const String &str);bool operator == (const String &other);//判断相等int getLength();//返回长度private:char *m_data;//私有变量
};String::String(const char* str){if(str==NULL){m_data=new char[1];*m_data='\0';}else{m_data=new char[strlen(str)+1];strcpy(m_data,str);}
}
String::String(const String &other){//拷贝构造函数if(other.m_data==NULL){m_data=NULL;}m_data=new char[strlen(other.m_data)+1];strcpy(m_data,other.m_data);
}String::~String(){ //析构函数if(m_data!=NULL){delete [] m_data;m_data=NULL;}}String & String::operator=(const String &other){//赋值函数if(this!=&other){delete [] m_data;if(!other.m_data)m_data=NULL;else{m_data=new char[strlen(other.m_data)+1];strcpy(m_data,other.m_data);}}return *this;}String & String::operator+(const String &other){//字符串连接String newString;if(other.m_data==NULL){newString=*this;}else if(m_data==NULL){newString=other;}else{newString.m_data=new char[strlen(other.m_data)+strlen(m_data)+1];strcpy(newString.m_data,m_data);strcat(newString.m_data,other.m_data);}return newString;
}bool String::operator == (const String &other){if(strlen(m_data)!=strlen(other.m_data))return false;elsereturn strcmp(m_data,other.m_data)?false:true;
}int String::getLength(){//返回长度return strlen(m_data);
}ostream & operator<<(ostream &os,const String &str){os<<str.m_data;return os;
}int main(){char* str="hello";String str1(str);cout<<"str1"<<str1<<endl;String str2("world!");cout<<"str2"<<str2<<endl;String str3(str1);cout<<"str3"<<str3<<endl;str3=str2;cout<<"str3"<<str3<<endl;cout<<str1.getLength()<<endl;char *p=NULL;cout<<"strlen(NULL)="<<strlen(p)<<endl;return 0;
}

输入输出运算符的重载相关推荐

  1. C++ 运算符的重载

    目录 一.原理和机制 二.双目运算符的重载 三.隐式转换 四.单目运算符的重载 五.运算符重载的限制 六.特殊运算符的重载 1.数组对象 2.强转和函数对象 3.指针对象 一.原理和机制 C++中运算 ...

  2. # c++运算符重载之 前置++, 后置++, 负号运算符, 类型转换函数, 以及输入输出运算符...

    c++运算符重载之 前置++, 后置++, 负号运算符, 类型转换函数, 以及输入输出运算符 标签(空格分隔): c++ 前言 我在c++学习的过程中, 对这几个不太常见的运算符重载不太会写.出现了很 ...

  3. C++输入输出运算符重载(“”“”)

    //输入输出运算符只能用友元函数重载 #include <iostream> #include <assert.h> #include <string.h> usi ...

  4. 运算符重载(加减运算符、前置加加(减减)后置加加(减减)运算符、赋值运算符、输入输出运算符、关系运算符、函数调用)

    编译器对于一个类会默认生成以几种函数: 1.默认构造函数(空形参,空函数体) 2.默认拷贝构造函数(浅拷贝,也叫值拷贝.字节拷贝) 3.析构函数(空形参,空函数体.析构函数要求形参列表必须是空的,所以 ...

  5. C++——运算符的重载---以成员函数方式重载---以友元函数方式重载

    一.运算符的重载 1.运算符的重载 允许把标准运算符(如+ - * /等运算符)应用于自定义数据类型的对象,可以提高程序的可读性,运算符的重载本质上还是函数重载.运算符仅仅是语法上的方便,它是另一种函 ...

  6. C++知识点39——运算符的重载概念与分数类实现(上)

    一.概念 在博客https://blog.csdn.net/Master_Cui/article/details/109461561已经提到了赋值运算符的重载,重载运算符是有特殊名字的函数:名字由op ...

  7. C++知识点43——解引用运算符和箭头运算符的重载及智能指针类的实现

    一.概念. 在自定义行为类似指针的类时,需要重载*和->.C++中的智能指针就重载了这两个运算符.->必须是成员函数,*也应该是成员函数.与内置类型保持一致,这两个函数通常都是const的 ...

  8. C++知识点42——下标运算符[]的重载及string类的实现

    一.下标运算符的重载 1.概念 如果一个类表示容器,那么要重载下标运算符[],下标运算符必须是成员函数.下表访问运算符通常要有一个const版本和一个非const版本.如果不定义const版本,那么c ...

  9. C++知识点41——运算符的重载概念与分数类实现(下)

    接上篇文章https://blog.csdn.net/Master_Cui/article/details/109515571继续实现分数类和相关运算符的重载 6.自增自减运算符(++ --)的重载 ...

  10. C++知识点40——运算符的重载概念与分数类实现(中)

    接上篇文章https://blog.csdn.net/Master_Cui/article/details/109515376,继续实现分数类和相关运算符的重载 3.重载算术运算符和复合赋值运算符 算 ...

最新文章

  1. Node.js的url模块简介
  2. Page.ClientScript.RegisterStartupScript函数的使用
  3. 人参的用法 和 吃法
  4. 3.游戏优化(CCSpriteBatchNode)
  5. RAC Failover三种方式
  6. 我三年开发经验,从字节跳动抖音离职后,吐血整理
  7. 这款堪称完美的PDF编辑器,帮你节省50%的写作时间
  8. 计算机的组成 —— 显卡
  9. 在Python中使用XGBoost和scikit-learn进行随机梯度增强
  10. E-prime主要常见问题及matlab、python打marker方式
  11. 巨波公第3子登国公后裔在荆州(巨波公6子的后裔,全部水落石出)
  12. 圈粉无数!被称为B站“新垣结衣”的UP主,如何收获Z世代年轻人的喜爱?
  13. 区块链中国专利分析报告.20180309
  14. Windows运行机理——消息与消息队列
  15. SSM+网上书店管理系统 毕业设计-附源码082255
  16. python opencv 直方图均衡_深入理解OpenCV+Python直方图均衡化
  17. SQL文件的导入与导出
  18. git revert回退时提示One or more files are in a conflicted state
  19. PHP反序列化与SESSION
  20. 赵小楼《天道》《遥远的救世主》问答集(1)每一条评论都是一个独立意识所展现的相,在这是用文字问答的形式呈现出来的相

热门文章

  1. Ros基本概念及小乌龟程序学习
  2. Win10安装JDK与配置环境变量
  3. JSP — request 内置对象
  4. Android EditText 常用属性总结
  5. shell编程sed命令替换文件内容
  6. tensorflow构建CNN模型时的常用接口函数
  7. 期货结算 期货算法公式
  8. 《上古天真论》第六讲文字版
  9. MVC之使用Nhibernate
  10. PyQt之按钮传递鼠标按下事件点击失效