C++過載流插入運算子和流提取運算子
阿新 • • 發佈:2019-01-26
C++的流插入運算子“<<”和流提取運算子“>>”是C++在類庫中提供的,所有C++編譯系統都在類庫中提供輸入流類istream和輸出流類ostream。cin和cout分別是istream類和ostream類的物件。在類庫提供的標頭檔案中已經對“<<”和“>>”進行了過載,使之作為流插入運算子和流提取運算子,能用來輸出和輸入C++標準型別的資料。因此,凡是用“cout<<”和“cin>>”對標準型別資料進行輸入輸出的,都要用#include 把標頭檔案包含到本程式檔案中。
使用者自己定義的型別的資料,是不能直接用“<<”和“>>”來輸出和輸入的。如果想用它們輸出和輸入自己宣告的型別的資料,必須對它們過載。
對“<<”和“>>”過載的函式形式如下:
istream & operator >> (istream &, 自定義類 &);
ostream & operator << (ostream &, 自定義類 &);
即過載運算子“>>”的函式的第一個引數和函式的型別都必須是istream&型別,第二個引數是要進行輸入操作的類。過載“<<”的函式的第一個引數和函式的型別都必須是ostream&型別,第二個引數是要進行輸出操作的類。因此,只能將過載“>>”和“<<”的函式作為友元函式或普通的函式,而不能將它們定義為成員函式。
在程式中,人們希望能用插入運算子“<<”來輸出使用者自己宣告的類的物件的資訊,這就需要過載流插入運算子“<<”。
[例10.7] 在例10.2的基礎上,用過載的“<<”輸出複數。
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)
以上執行結果無疑是正確的,但並不完善。在輸入複數的虛部為正值時,輸出的結果是沒有問題的,但是虛部如果是負數,就不理想,請觀察輸出結果。
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)
根據先除錯通過,最後完善的原則,可對程式作必要的修改。將過載運算子“<<”函式修改如下:
可以看到,在C++中,運算子過載是很重要的、很有實用意義的。它使類的設計更加豐富多彩,擴大了類的功能和使用範圍,使程式易於理解,易於對物件進行操作,它體現了為使用者著想、方便使用者使用的思想。有了運算子過載,在聲明瞭類之後,人們就可以像使用標準型別一樣來使用自己宣告的類。類的宣告往往是一勞永逸的,有了好的類,使用者在程式中就不必定義許多成員函式去完成某些運算和輸入輸出的功能,使主函式更加簡單易讀。好的運算子過載能體現面向物件程式設計思想。
可以看到,在運算子過載中使用引用(reference)的重要性。利用引用作為函式的形參可以在呼叫函式的過程中不是用傳遞值的方式進行虛實結合,而是通過傳址方式使形參成為實參的別名,因此不生成臨時變數(實參的副本),減少了時間和空間的開銷。此外,如果過載函式的返回值是物件的引用時,返回的不是常量,而是引用所代表的物件,它可以出現在賦值號的左側而成為左值(left value),可以被賦值或參與其他操作(如保留cout流的當前值以便能連續使用“<<”輸出)。但使用引用時要特別小心,因為修改了引用就等於修改了它所代表的物件。
使用者自己定義的型別的資料,是不能直接用“<<”和“>>”來輸出和輸入的。如果想用它們輸出和輸入自己宣告的型別的資料,必須對它們過載。
對“<<”和“>>”過載的函式形式如下:
istream & operator >> (istream &, 自定義類 &);
ostream & operator << (ostream &, 自定義類 &);
即過載運算子“>>”的函式的第一個引數和函式的型別都必須是istream&型別,第二個引數是要進行輸入操作的類。過載“<<”的函式的第一個引數和函式的型別都必須是ostream&型別,第二個引數是要進行輸出操作的類。因此,只能將過載“>>”和“<<”的函式作為友元函式或普通的函式,而不能將它們定義為成員函式。
過載流插入運算子“<<”
[例10.7] 在例10.2的基礎上,用過載的“<<”輸出複數。
- #include <iostream>
- using namespace std;
- classComplex
- {
- public:
- Complex( ){real=0;imag=0;}
- Complex(double r,double i){real=r;imag=i;}
- Complexoperator + (Complex&c2); //運算子“+”過載為成員函式
- friend
- private:
- double real;
- double imag;
- };
- ComplexComplex::operator + (Complex&c2)//定義運算子“+”過載函式
- {
- return Complex(real+c2.real,imag+c2.imag);
- }
- ostream& operator << (ostream& output,Complex& c) //定義運算子“<<”過載函式
- {
- output<<"("<<c.real<<"+"<<c.imag<<"i)"<<endl;
- return output;
- }
- int main( )
- {
- Complexc1(2,4),c2(6,10),c3;
- c3=c1+c2;
- cout<<c3;
- return 0;
- }
過載流提取運算子“>>”
C++預定義的運算子“>>”的作用是從一個輸入流中提取資料,如“cin>>i;”表示從輸入流中提取一個整數賦給變數i(假設已定義i為int型)。過載流提取運算子的目的是希望將“>>”用於輸入自定義型別的物件的資訊。[例10.8] 在例10.7的基礎上,增加過載流提取運算子“>>”,用“cin>>”輸入複數,用“cout<<”輸出複數。- #include <iostream>
- using namespace std;
- classComplex
- {
- public:
- friend ostream& operator << (ostream&,Complex&); //宣告過載運算子“<<”
- friend istream& operator >> (istream&,Complex&); //宣告過載運算子“>>”
- private:
- double real;
- double imag;
- };
- ostream& operator << (ostream& output,Complex& c) //定義過載運算子“<<”
- {
- output<<"("<<c.real<<"+"<<c.imag<<"i)";
- return output;
- }
- istream& operator >> (istream& input,Complex& c) //定義過載運算子“>>”
- {
- cout<<"input real part and imaginary part of complex number:";
- input>>c.real>>c.imag;
- return input;
- }
- int main( )
- {
- Complexc1,c2;
- cin>>c1>>c2;
- cout<<"c1="<<c1<<endl;
- cout<<"c2="<<c2<<endl;
- return 0;
- }
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)
以上執行結果無疑是正確的,但並不完善。在輸入複數的虛部為正值時,輸出的結果是沒有問題的,但是虛部如果是負數,就不理想,請觀察輸出結果。
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)
根據先除錯通過,最後完善的原則,可對程式作必要的修改。將過載運算子“<<”函式修改如下:
- ostream& operator << (ostream& output,Complex& c)
- {
- output<<"("<<c.real;
- if(c.imag>=0) output<<"+";//虛部為正數時,在虛部前加“+”號
- output<<c.imag<<"i)"<<endl; //虛部為負數時,在虛部前不加“+”號
- return output;
- }
可以看到,在C++中,運算子過載是很重要的、很有實用意義的。它使類的設計更加豐富多彩,擴大了類的功能和使用範圍,使程式易於理解,易於對物件進行操作,它體現了為使用者著想、方便使用者使用的思想。有了運算子過載,在聲明瞭類之後,人們就可以像使用標準型別一樣來使用自己宣告的類。類的宣告往往是一勞永逸的,有了好的類,使用者在程式中就不必定義許多成員函式去完成某些運算和輸入輸出的功能,使主函式更加簡單易讀。好的運算子過載能體現面向物件程式設計思想。
可以看到,在運算子過載中使用引用(reference)的重要性。利用引用作為函式的形參可以在呼叫函式的過程中不是用傳遞值的方式進行虛實結合,而是通過傳址方式使形參成為實參的別名,因此不生成臨時變數(實參的副本),減少了時間和空間的開銷。此外,如果過載函式的返回值是物件的引用時,返回的不是常量,而是引用所代表的物件,它可以出現在賦值號的左側而成為左值(left value),可以被賦值或參與其他操作(如保留cout流的當前值以便能連續使用“<<”輸出)。但使用引用時要特別小心,因為修改了引用就等於修改了它所代表的物件。