詳解C++編程中的重載流插入運(yùn)算符和流提取運(yùn)算符
C++的流插入運(yùn)算符“<<”和流提取運(yùn)算符“>>”是C++在類庫中提供的,所有C++編譯系統(tǒng)都在類庫中提供輸入流類istream和輸出流類ostream。cin和cout分別是istream類和ostream類的對象。在類庫提供的頭文件中已經(jīng)對“<<”和“>>”進(jìn)行了重載,使之作為流插入運(yùn)算符和流提取運(yùn)算符,能用來輸出和輸入C++標(biāo)準(zhǔn)類型的數(shù)據(jù)。因此,凡是用“cout<<”和“cin>>”對標(biāo)準(zhǔn)類型數(shù)據(jù)進(jìn)行輸入輸出的,都要用#include 把頭文件包含到本程序文件中。
用戶自己定義的類型的數(shù)據(jù),是不能直接用“<<”和“>>”來輸出和輸入的。如果想用它們輸出和輸入自己聲明的類型的數(shù)據(jù),必須對它們重載。
對“<<”和“>>”重載的函數(shù)形式如下:
istream & operator >> (istream &, 自定義類 &); ostream & operator << (ostream &, 自定義類 &);
即重載運(yùn)算符“>>”的函數(shù)的第一個(gè)參數(shù)和函數(shù)的類型都必須是istream&類型,第二個(gè)參數(shù)是要進(jìn)行輸入操作的類。重載“<<”的函數(shù)的第一個(gè)參數(shù)和函數(shù)的類型都必須是ostream&類型,第二個(gè)參數(shù)是要進(jìn)行輸出操作的類。因此,只能將重載“>>”和“<<”的函數(shù)作為友元函數(shù)或普通的函數(shù),而不能將它們定義為成員函數(shù)。
重載流插入運(yùn)算符“<<”
在程序中,人們希望能用插入運(yùn)算符“<<”來輸出用戶自己聲明的類的對象的信息,這就需要重載流插入運(yùn)算符“<<”。
[例] 用重載的“<<”輸出復(fù)數(shù)。
#include <iostream>
using namespace std;
class Complex
{
  public:
  Complex( ){real=0;imag=0;}
  Complex(double r,double i){real=r;imag=i;}
  Complex operator + (Complex &c2); //運(yùn)算符“+”重載為成員函數(shù)
  friend ostream& operator << (ostream&,Complex&); //運(yùn)算符“<<”重載為友元函數(shù)
  private:
  double real;
  double imag;
};
Complex Complex::operator + (Complex &c2)//定義運(yùn)算符“+”重載函數(shù)
{
  return Complex(real+c2.real,imag+c2.imag);
}
ostream& operator << (ostream& output,Complex& c) //定義運(yùn)算符“<<”重載函數(shù)
{
  output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
  return output;
}
int main( )
{
  Complex c1(2,4),c2(6,10),c3;
  c3=c1+c2;
  cout<<c3;
  return 0;
}
注意,在Visual C++ 6.0環(huán)境下運(yùn)行時(shí),需將第一行改為#include <iostream.h>,并刪去第2行,否則編譯不能通過。運(yùn)行結(jié)果為:
(8+14i)
可以看到在對運(yùn)算符“<<”重載后,在程序中用“<<”不僅能輸出標(biāo)準(zhǔn)類型數(shù)據(jù),而且可以輸出用戶自己定義的類對象。用“cout<<c3”即能以復(fù)數(shù)形式輸出復(fù)數(shù)對象c3的值。形式直觀,可讀性好,易于使用。
下面對怎樣實(shí)現(xiàn)運(yùn)算符重載作一些說明。程序中重載了運(yùn)算符“<<”,運(yùn)算符重載函數(shù)中的形參output是ostream類對象的引用,形參名output是用戶任意起的。分析main函數(shù)最后第二行:
cout<<c3;
運(yùn)算符“<<”的左面是cout,前面已提到cout是ostream類對象?!?lt;<”的右面是c3,它是Complex類對象。由于已將運(yùn)算符“<<”的重載函數(shù)聲明為Complex類的友元函數(shù),編譯系統(tǒng)把“cout<<c3”解釋為
operator<<(cout, c3)
即以cout和c3作為實(shí)參,調(diào)用下面的operator<<函數(shù):
  ostream& operator<<(ostream& output,Complex& c)
  {
    output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
    return output;
  }
調(diào)用函數(shù)時(shí),形參output成為cout的引用,形參c成為c3的引用。因此調(diào)用函數(shù)的過程相當(dāng)于執(zhí)行:
cout<<″(″<<c3.real<<″+″<<c3.imag<<″i)″<<endl; return cout;
請注意,上一行中的“<<”是C++預(yù)定義的流插入符,因?yàn)樗覀?cè)的操作數(shù)是字符串常量和double類型數(shù)據(jù)。執(zhí)行cout語句輸出復(fù)數(shù)形式的信息。然后執(zhí)行return語句。
請思考,return output的作用是什么?回答是能連續(xù)向輸出流插入信息。output是ostream類的對象,它是實(shí)參cout的引用,也就是cout通過傳送地址給output,使它們二者共享同一段存儲(chǔ)單元,或者說output是cout的別名。因此,return output就是return cout,將輸出流cout的現(xiàn)狀返回,即保留輸出流的現(xiàn)狀。
請問返回到哪里?剛才是在執(zhí)行
cout<<c3;
在已知cout<<c3的返回值是cout的當(dāng)前值。如果有以下輸出:
cout<<c3<<c2;
先處理
cout<<c3
即
(cout<<c3)<<c2;
而執(zhí)行(cout<<c3)得到的結(jié)果就是具有新內(nèi)容的流對象cout,因此,(cout<<c3)<<c2相當(dāng)于cout(新值)<<c2。運(yùn)算符“<<”左側(cè)是ostream類對象cout,右側(cè)是Complex類對象c2,則再次調(diào)用運(yùn)算符“<<”重載函數(shù),接著向輸出流插入c2的數(shù)據(jù)。現(xiàn)在可以理解了為什么C++規(guī)定運(yùn)算符“<<”重載函數(shù)的第一個(gè)參數(shù)和函數(shù)的類型都必須是ostream類型的引用,就是為了返回cout的當(dāng)前值以便連續(xù)輸出。
請讀者注意區(qū)分什么情況下的“<<”是標(biāo)準(zhǔn)類型數(shù)據(jù)的流插入符,什么情況下的“<<”是重載的流插入符。如
cout<<c3<<5<<endl;
有下劃線的是調(diào)用重載的流插入符,后面兩個(gè)“<<”不是重載的流插入符,因?yàn)樗挠覀?cè)不是Complex類對象而是標(biāo)準(zhǔn)類型的數(shù)據(jù),是用預(yù)定義的流插入符處理的。
還有一點(diǎn)要說明,在本程序中,在Complex類中定義了運(yùn)算符“<<”重載函數(shù)為友元函數(shù),因此只有在輸出Complex類對象時(shí)才能使用重載的運(yùn)算符,對其他類型的對象是無效的。如
cout<<time1; //time1是Time類對象,不能使用用于Complex類的重載運(yùn)算符
重載流提取運(yùn)算符“>>”
C++預(yù)定義的運(yùn)算符“>>”的作用是從一個(gè)輸入流中提取數(shù)據(jù),如“cin>>i;”表示從輸入流中提取一個(gè)整數(shù)賦給變量i(假設(shè)已定義i為int型)。重載流提取運(yùn)算符的目的是希望將“>>”用于輸入自定義類型的對象的信息。
[例] 在上例的基礎(chǔ)上,增加重載流提取運(yùn)算符“>>”,用“cin>>”輸入復(fù)數(shù),用“cout<<”輸出復(fù)數(shù)。
#include <iostream>
using namespace std;
class Complex
{
  public:
  friend ostream& operator << (ostream&,Complex&); //聲明重載運(yùn)算符“<<”
  friend istream& operator >> (istream&,Complex&); //聲明重載運(yùn)算符“>>”
  private:
  double real;
  double imag;
};
ostream& operator << (ostream& output,Complex& c) //定義重載運(yùn)算符“<<”
{
  output<<"("<<c.real<<"+"<<c.imag<<"i)";
  return output;
}
istream& operator >> (istream& input,Complex& c) //定義重載運(yùn)算符“>>”
{
  cout<<"input real part and imaginary part of complex number:";
  input>>c.real>>c.imag;
  return input;
}
int main( )
{
  Complex c1,c2;
  cin>>c1>>c2;
  cout<<"c1="<<c1<<endl;
  cout<<"c2="<<c2<<endl;
  return 0;
}
運(yùn)行情況如下:
input real part and imaginary part of complex number:3 6↙ input real part and imaginary part of complex number:4 10↙ c1=(3+6i) c2=(4+10i)
以上運(yùn)行結(jié)果無疑是正確的,但并不完善。在輸入復(fù)數(shù)的虛部為正值時(shí),輸出的結(jié)果是沒有問題的,但是虛部如果是負(fù)數(shù),就不理想,請觀察輸出結(jié)果。
input real part and imaginary part of complex number:3 6↙ input real part and imaginary part of complex number:4 -10↙ c1=(3+6i) c2=(4+-10i)
根據(jù)先調(diào)試通過,最后完善的原則,可對程序作必要的修改。將重載運(yùn)算符“<<”函數(shù)修改如下:
ostream& operator << (ostream& output,Complex& c)
{
  output<<"("<<c.real;
  if(c.imag>=0) output<<"+";//虛部為正數(shù)時(shí),在虛部前加“+”號(hào)
  output<<c.imag<<"i)"<<endl; //虛部為負(fù)數(shù)時(shí),在虛部前不加“+”號(hào)
  return output;
}
這樣,運(yùn)行時(shí)輸出的最后一行為c2=(4-10i) 。
可以看到,在C++中,運(yùn)算符重載是很重要的、很有實(shí)用意義的。它使類的設(shè)計(jì)更加豐富多彩,擴(kuò)大了類的功能和使用范圍,使程序易于理解,易于對對象進(jìn)行操作,它體現(xiàn)了為用戶著想、方便用戶使用的思想。有了運(yùn)算符重載,在聲明了類之后,人們就可以像使用標(biāo)準(zhǔn)類型一樣來使用自己聲明的類。類的聲明往往是一勞永逸的,有了好的類,用戶在程序中就不必定義許多成員函數(shù)去完成某些運(yùn)算和輸入輸出的功能,使主函數(shù)更加簡單易讀。好的運(yùn)算符重載能體現(xiàn)面向?qū)ο蟪绦蛟O(shè)計(jì)思想。
可以看到,在運(yùn)算符重載中使用引用(reference)的重要性。利用引用作為函數(shù)的形參可以在調(diào)用函數(shù)的過程中不是用傳遞值的方式進(jìn)行虛實(shí)結(jié)合,而是通過傳址方式使形參成為實(shí)參的別名,因此不生成臨時(shí)變量(實(shí)參的副本),減少了時(shí)間和空間的開銷。此外,如果重載函數(shù)的返回值是對象的引用時(shí),返回的不是常量,而是引用所代表的對象,它可以出現(xiàn)在賦值號(hào)的左側(cè)而成為左值(left value),可以被賦值或參與其他操作(如保留cout流的當(dāng)前值以便能連續(xù)使用“<<”輸出)。但使用引用時(shí)要特別小心,因?yàn)樾薷牧艘镁偷扔谛薷牧怂淼膶ο蟆?/p>
上一篇:C++中與輸入相關(guān)的istream類成員函數(shù)簡介
欄 目:C語言
本文標(biāo)題:詳解C++編程中的重載流插入運(yùn)算符和流提取運(yùn)算符
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/2689.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
 - 01-10求子數(shù)組最大和的解決方法詳解
 - 01-10深入二叉樹兩個(gè)結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)的詳解
 - 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)- 解析最少換車次數(shù)的問題詳解
 - 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)-用棧實(shí)現(xiàn)表達(dá)式求值的方法詳解
 - 01-10HDOJ 1443 約瑟夫環(huán)的最新應(yīng)用分析詳解
 - 01-10深入理解C++中常見的關(guān)鍵字含義
 - 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
 - 01-10如何查看進(jìn)程實(shí)際的內(nèi)存占用情況詳解
 - 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
 


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
 - 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
 - 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
 - 04-02c語言用函數(shù)寫分段 用c語言表示分段
 - 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
 - 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
 - 04-02c語言沒有round函數(shù) round c語言
 - 04-02c語言分段函數(shù)怎么求 用c語言求分段
 - 04-02C語言中怎么打出三角函數(shù) c語言中怎
 - 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
 
隨機(jī)閱讀
- 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
 - 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
 - 04-02jquery與jsp,用jquery
 - 01-10delphi制作wav文件的方法
 - 01-11ajax實(shí)現(xiàn)頁面的局部加載
 - 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
 - 01-10C#中split用法實(shí)例總結(jié)
 - 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
 - 08-05DEDE織夢data目錄下的sessions文件夾有什
 - 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
 


