C++操作符重載學習與使用-算數運算符、賦值、自增、輸入輸出操作符

C++操作符重載學習與使用-算數運算符、賦值、自增、輸入輸出操作符

操作符重載概念

class Complex
{
	int real;
	int img;
public:
	Complex():real(0),img(0){};
	Complex(int r,int i):real(r),img(i){};
}

Complex c1;
Complex c2 = Complex(1,2);

c1 + c2;
// 嘗試進行 C1 + C2 的操作

程序運行報錯,說明對於 c1c2 來說,是無法直接進行算術運算符操作的,可以重定義或重載大部分 C++ 內置的運算符,這樣就能使用自定義類型的運算符進行操作,這裏將進行算術運算符的重載。

首先來看一個常規操作

Complex addNumber(Complex &p1)
{
	Complex p3;
	p3.real = this->real + p1.real;
	p3.img = this->img + p1.img;
	return p3;
}

Complex c3 = c1.addNumber(c2);

這種方式看起來可以實現,但是每次都需要調用函數去計算,如何進行化簡呢?

Complex operator+(Complex &p1)
{
	Complex p3;
	p3.real = this->real + p1.real;
	p3.img = this->img + p1.img;
	return p3;
}

Complex c3 = c1 + c2;
// 等價於 Complex c3 = c1.operator+(c2);

以上就是算數運算符重載的實現方式,這種方式叫做成員函數重載,此外,還可以定義友元方式的重載。
首先在類中聲明友元函數

friend Complex operator+(Complex &p1, Complex &p2);

由於友元是沒有 this 指針的,所以要標明形參。

Complex operator+(Complex &p1, Complex &p2)
{
	Complex p3;
	p3.real = p1.real + p2.real;
	p3.img = p1.img + p2.img;
	return p3;
}

友元調用形式爲:

Complex c3 = c1 + c2;
// 等價於 Complex c3 = operator+(c1, c2);

注意:對於不是一定需要 this 指針的一般定義爲友元重載,會讓調用更加方便。爲什麼這麼說呢,看個例子,如果是 int k = a + b; 的形式,使用成員函數重載是沒問題的,a是一個對象可以調用 this 指針,但是如果是 int k = 1 + b;,那麼對成員是不可行的,而友元可行。

賦值操作符重載

Complex c3 = c2;  // 調用拷貝構造函數

Complex c3;
c3 = c2;  // 不會調用拷貝構造函數
// 這是因爲編譯器會默認合成一個賦值運算符重載函數

這裏的賦值運算符重載函數必須要定義爲成員函數,因爲它一定需要用到 this 指針。

Complex &operator=(const Complex &c)
{
	if(this != &c)  // 因爲 this 是一個非 const,而c是const,所以不能寫成 *this != c
	{	
		real = c.real;
		img = c.img;
	}
	return *this;
}

自增運算符重載

自增運算符的重載包括兩種,一種是前置++,一種是後置++

Complex &operator++()
{	// 前置++
	real++;
	img++;
	return *this;
}

Complex c3;
++c3;
Complex operator++(int i)  // 這裏的 int i 僅僅用於區別重載
{	// 後置++
	real++;
	img++;
	return *this;
}

Complex c3;
c3++;

前置++版本返回值爲引用,其表示進行++之後的對象;而後置++表示++之前的值的對象。這樣來看,其實上面後置++的寫法是有問題的,既然後置++表示++之前的值的對象,那麼應該這樣寫:

Complex operator++(int i)   // 這裏的 int i 僅僅用於區別重載
{	// 後置++
	Complex tmp = *this;
	real++;
	img++;
	return tmp;
}

Complex c3;
c3++;

輸入輸出操作符重載

1、輸出操作符重載,不能定義爲成員函數(因爲如果是成員函數,左側的運算對象必須是本類的對象);
2、可以定義爲友元,以便訪問私有域;
3、需要 out 內容。

friend void operator<<(ostream &out, const Complex &c);
void operator<<(ostream &out, const Complex &c)   // 這裏需要輸出對象out
{
	cout << c.real << "+" << c.img <<endl;
}

採用上述方法時,沒有辦法連續輸出,因爲前部分返回類型 void,不能再繼續被使用。爲了能夠進行連續輸出,需要將返回值定義爲 ostream 的引用。

ostream & operator<<(ostream &out, const Complex &c)
{
	cout << c.real << "+" << c.img;  //儘量不要在函數中添加換行符
	return out;
}

cout << c1 << c2 << c3;

ostreamoutput stream的簡稱,即輸出流,在C++中用來輸出。一個典型的輸出流對象就是在C++中標準輸出流cout。在C++中,很少自定義ostream的對象,更多的是直接使用coutostream這個類型,往往出現在<<操作重載中,作爲某個類的友元函數出現。

類似的,對於輸入操作符的重載,只需要修改以下細節:

iostream & operator>>(istream &in, Complex &c)
{
	in >> c.real;
	in >> c.img;
	return in;
}

cin >> c3;

因爲需要修改值,所以不能使用 const 修飾 c

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章