1. 程式人生 > >過載輸入輸出運算子引用的理解

過載輸入輸出運算子引用的理解

#include <iostream.h>
class coord{
	int x,y;
public:
	coord(int i=0,int j=0)
	{
		x=i;
		y=j;
	}
	friend ostream& operator<<(ostream  &stream,coord &ob);//這裡第二個引數採用了引用(&ob),
	//是為了減少呼叫的開銷,使用引用引數只需把物件的地址傳進來就可以了,而不需把每個域分量逐一傳進來
	//而消耗記憶體和時間。所以不用普通的物件做引數,雖然結果一樣。但是<<過載的函式返回值和第一個引數必須為輸出流類ostream的的引用。
	friend istream& operator>>(istream &input,coord &ob);//這裡的第二個引數必須為引用,目的是函式體對引數a的修改能影響實參,因為從輸入
	//流輸入的值要存入與a對應的實參中。注意過載輸出<<時的作用並不是為了修改實參,此點不同。
};

ostream &  operator<<(ostream &stream,coord &ob)
{
	stream<<ob.x<<","<<ob.y<<endl;//stream為ostream類的一個物件的引用,作為左運算元(cout也是一樣,是C++中的兩個流物件)
	return stream;
}

istream& operator>>(istream &input,coord &ob)
{
	cout<<"Enter x and y value:";
	input>>ob.x;
	input>>ob.y;
	return input;
}

main()
{
	coord a(55,66),b(100,220);
	cout<<a<<b;
	cin>>a;
	cin>>b;
	cout<<a<<b;
	return 0;
}

分析:上面輸出過載函式的形參stream是ostream類物件的引用,返回值也是ostream類物件的引用。在main中cout<<a;cout是ostream類物件,a是coord類物件,所以可以把其理解為
operator<<(cout,a);
其中cout和a作為了實參,呼叫了
ostream &  operator<<(ostream &stream,coord &ob)
{
	stream<<ob.x<<","<<ob.y<<endl;
	return stream;
}
也就是相當於stream是cout的引用,ob為a的引用。由此其相當於執行了:
cout<<a.x<<","<<a.y<<endl;
return cout;

此時,返回值是一個ostream類物件的引用,即將輸出流cout返回了,當執行cout<<a<<b;時,可以等價為(cout<<a)<<b;(cout<<a)是具有新內容的流物件cout,(cout<<a)<<b就相當於(新cout)<<b,操作符左側仍是ostream類物件cout,所有再次呼叫<<過載可以繼續輸出資料。因此,C++規定運算子<<過載函式的第一個引數和函式返回型別必須是ostream型別的引用,就是為了返回cout的當前值連續的輸出。

另附面試經典的問題:流操作符過載返回值申明為“引用”的作用:

流操作符<<和>>,這兩個操作符常常希望被連續使用,例如:cout << "hello" << endl; 因此這兩個操作符的返回值應該是一個仍然支援這兩個操作符的流引用。可選的其它方案包括:返回一個流物件和返回一個流物件指標。但是對於返回一個流物件,程式必須重新(拷貝)構造一個新的流物件,也就是說,連續的兩個<<操作符實際上是針對不同物件的!這無法讓人接受。對於返回一個流指標則不能連續使用<<操作符。因此,返回一個流物件引用是惟一選擇。這個唯一選擇很關鍵,它說明了引用的重要性以及無可替代性,也許這就是C++語言中引入引用這個概念的原因吧。賦值操作符=。這個操作符象流操作符一樣,是可以連續使用的,例如:x = j = 10;或者(x=10)=100;賦值操作符的返回值必須是一個左值,以便可以被繼續賦值。因此引用成了這個操作符的惟一返回值選擇。