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 的操作
程序運行報錯,說明對於 c1
和 c2
來說,是無法直接進行算術運算符操作的,可以重定義或重載大部分 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;
ostream
是output stream
的簡稱,即輸出流,在C++中用來輸出。一個典型的輸出流對象就是在C++中標準輸出流cout
。在C++中,很少自定義ostream
的對象,更多的是直接使用cout
。ostream
這個類型,往往出現在<<
操作重載中,作爲某個類的友元函數出現。
類似的,對於輸入操作符的重載,只需要修改以下細節:
iostream & operator>>(istream &in, Complex &c)
{
in >> c.real;
in >> c.img;
return in;
}
cin >> c3;
因爲需要修改值,所以不能使用 const
修飾 c
。