输入输出运算符的重载

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

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*指针指向的内容转换成 float
    sTmp = 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;
	else
	return 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焱齿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值