重載輸入輸出運算符
我們平時可以用流 std::cout<<str<<n ; std::cin>>str>>n ; 輸出、輸入字符串和整型等內置類型的值。但是對於我們自定義的類,比如 Student 類,卻不能直接通過 cout<<Student 或 cin>>Student 這樣的形式來輸出類的內容或給類賦值。怎麼辦呢?我們可以通過重載輸出、輸入運算符,讓自定義的類也支持這樣的操作。
重載輸出運算符
- 通常情況下,輸出運算符的第一個形參是一個非常量的ostream 對象的引用。(非常量是因爲向流寫入內容會改變其狀態; 用引用是因爲流對象不支持複製)
- 第二個參數一般來說是一個常量的引用,該常量是我們想要輸出的類類型。(用引用是因爲我們希望避免複製實參; 用常量是因爲通常打印對象的時候不需要改變對象的內容)
- 輸出運算符應儘量減少格式化的操作,尤其是換行符,這樣有利於用戶對輸出格式的控制。
- 一般會聲明爲友元函數(friend),這樣輸出運算符函數才能使用類的私有成員
- 輸入、輸出運算符都必須是非成員函數。否則,他們的左側運算對象將是我們的類的一個對象。
//例如,假設我們定義了類Student,輸出運算符函數爲成員函數
class Student{
...
ostream &operator<<(ostream &os);
...
};
...
Student stu;
//爲了直觀,用這種方式調用輸出運算符函數
stu.operator<<(cout); //等價於,stu<<cout ,顯然已經錯了
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 下面是一個例子:
#include<iostream>
using namespace std;
class Student
{
public:
Student(int x,string s)
{
num = x;
name = s;
}
friend ostream &operator<<(ostream &os,const Student &stu); //聲明爲友元
private:
int num;
string name;
};
ostream &operator<<(ostream &os,const Student &stu)
{
os<<stu.num<<" "<<stu.name;
return os;
}
int main()
{
Student stu(10,"liu");
//調用者在使用的時候決定是否換行
cout<<stu<<endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
重載輸入運算符
- 通常情況下,輸入運算符的第一個形參是運算符將要讀取的流的引用,第二個形參是將要讀入到的(非常量)對象的引用。(第二個形參非常量是因爲目的就是將數據讀入對象中,所以對象會被改變。)
- 該運算符通常會返回某個給定流的引用。
- 輸入運算符必須處理輸入可能失敗的情況,而輸出運算符不需要。
輸入時會發生的錯誤
可能會發生下列錯誤:
1. 當流含有錯誤類型的數據時讀取操作可能失敗(輸入數據與類型不匹配)。一旦發生錯誤,後續的流使用都將失敗。
2. 當讀取操作到達文件末尾或者遇到輸入流的其他錯誤時也會失敗。
檢查輸入是否成功
如果我們不進行錯誤判斷,可能會出現對象只有部分成員被賦了值,另外的成員未被賦值或賦值錯誤,這很可能導致該對象在以後的使用過程中引發錯誤。
解決的辦法是,對輸入結果進行判斷,如果輸入失敗,則將一個新的默認初始化的對象賦值給操作對象。
下面是一個例子(將上一個例子修改):
class Student
{
public:
//構造函數,列表初始化
Student():num(0),name(""){}
//重載輸出運算符
friend ostream &operator<<(ostream &os,const Student &stu); //聲明爲友元
//重載輸入運算符
friend istream &operator>>(istream &is,Student &stu);
private:
int num;
string name;
};
ostream &operator<<(ostream &os,const Student &stu)
{
os<<stu.num<<" "<<stu.name;
return os;
}
istream &operator>>(istream &is,Student &stu)
{
is>>stu.num>>stu.name;
//輸入判斷
if(!is)
stu = Student(); //如果失敗,默認初始化
return is;
}
int main()
{
Student stu;
cout<<"input:"<<endl;
//調用重載的輸入運算符函數
cin>>stu;
cout<<"output:";
//調用者在使用的時候決定是否換行
cout<<stu<<endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42