操作符過載 之 輸出操作符"
操作符過載 之 輸出操作符”<<”(C++)
- 問題背景
- 技術推演
- 解決方案
- 總結
閱讀之前注意:
本文閱讀建議用時:30min
本文閱讀結構如下表:
專案 | 下屬專案 | 測試用例數量 |
---|---|---|
問題背景 | 無 | 0 |
技術推演 | 無 | 2 |
解決方案 | 無 | 2 |
總結 | 無 | 0 |
問題背景
在C++中,我們自己定義了一個類,但我們卻不能用cout來直接輸出這個自定義類的具體物件。你可以試一試,編譯器會報錯的,這主要是因為編譯器不知道該按照什麼方式來輸出你自定義的類。
那我們就想用cout來直接輸出呢?怎麼辦呢?哈哈,我們有利器——操作符過載!這樣我們就可以規定輸出方式,有了規則,編譯器看到我們的這個類的物件就知道怎麼輸出了。
技術推演1
首先我們要承認的是,C++是把操作符過載用函式來實現的。2
比如我們要實現下面的自定義類A的物件的加法,該怎麼做呢?自然能夠想到的,就是用函式來把物件中的每個成員變數做加法,參考以下程式碼:
#include"iostream"
using namespace std;
class A{
public:
A(int a = 0, int b = 0)//使用預設引數,這樣既是有參建構函式,也是預設建構函式
{
this->a = a;
this->b = b;
}
public://為了方便起見,設定為public
int a;
int b;
};
A addA(A &A1,A &A2)//實現物件加法的函式
{
A tmp;
tmp.a = A1.a + A2.a;
tmp.b = A1.b + A2.b;
return tmp;
}
void main()
{
A a1(1, 2), a2(3, 4);
A a3 = addA(a1, a2);//用函式來做物件的加法
cout << "a" << a3.a << " b" << a3.b << endl;
system("pause" );
}
接下來我們看看操作符過載是怎麼用函式實現的:
#include"iostream"
using namespace std;
class A{
public:
A(int a = 0, int b = 0)//使用預設引數,這樣既是有參建構函式,也是預設建構函式
{
this->a = a;
this->b = b;
}
public://為了方便起見,設定為public
int a;
int b;
};
A operator+(A &A1,A &A2)//操作符過載
{
A tmp;//這裡會呼叫預設建構函式
tmp.a = A1.a + A2.a;
tmp.b = A1.b + A2.b;
return tmp;
}
void main()
{
A a1(1, 2), a2(3, 4);
A a4 = operator+(a1, a2);
A a5 = a1 + a2;
cout << "a" << a4.a << " b" << a4.b << endl;
cout << "a" << a5.a << " b" << a5.b << endl;
system("pause");
}
上面程式碼中是用全域性函式來實現操作符過載,事實上這並不是正規寫法,但為了方便理解,正不正規姑且不論。在main函式中,我們可以看到語句“A a4 = operator+(a1, a2);”和語句“A a5 = a1 + a2;”的效果都是一樣的。
因此我們可以推測,C++編譯器在看到自定義型別在做加法時,也就是看到+號,它會自動的呼叫過載函式,把左操作物件(+號左邊的物件)和右操作物件(+號右邊的物件)分別傳入過載函式。這樣一來,我們就知道C++確實是把操作符過載用函式來實現的。
解決方案
思路:根據以上的技術推演,我們可以同樣的應用在“<<”操作符上,那麼這個操作符過載的話,需要什麼引數呢?毫無疑問,我們自定義型別的物件的引數需要傳進去。
我們先看看以下程式碼:
#include"iostream"
using namespace std;
void main()
{
int a = 10;
char *b = "hello, world";
cout << a;
cout << b;
system("pause");
}
可以看到,基礎的型別(也就是int和字串指標型別)作為了引數,但還有一個引數,看來看去,就只有cout了=-=,哈哈,想不到吧,cout竟然也是一個引數。
其實如果我們右鍵檢視一下cout,就能看到下面圖片中的內容
看到了吧,cout前面帶著一個型別說明符“ostream”,即cout也是一個類的物件。
這樣我們就知道過載”<<”需要哪些引數了:一個是ostream型別的物件,還有一個就是我們自定義型別A的物件。
下面我們就來實現它!
參考以下程式碼:
#include"iostream"
using namespace std;
class A{
public:
A(int a = 0, int b = 0)//使用預設引數,這樣既是有參建構函式,也是預設建構函式
{
this->a = a;
this->b = b;
}
public://為了方便起見,設定為public
int a;
int b;
};
void operator<<(ostream &out,A &a1)//操作符過載
{
out << "a" << a1.a << " b" << a1.b << endl;//這裡直接用out
}
void main()
{
A a1(1, 2), a2(3, 4);
cout<<a1;
cout<<a2;
system("pause");
}
總結
事實上以上程式碼均不是正規寫法,正規寫法連結將在以後給出。
最後引用王保明先生的一句話來給本文做總結:“結論倍簡單的:首先我們要承認一件事,C++中操作符的過載是用函式來實現的”。