01 運算符重載的需求 C++ 預定義的運算符,只能用於基本數據類型的運算:整型、實型、字元型、邏輯型等等,且不能用於對象的運算。但是我們有時候又很需要在對象之間能用運算符,那麼這時我們就要 重載運算符 ,使得運算符能用於對象之間的運算。 比如,在數學上,兩個複數可以直接進行+、 等運算,但在C++ ...
01 運算符重載的需求
C++ 預定義的運算符,只能用於基本數據類型的運算:整型、實型、字元型、邏輯型等等,且不能用於對象的運算。但是我們有時候又很需要在對象之間能用運算符,那麼這時我們就要重載運算符,使得運算符能用於對象之間的運算。
比如,在數學上,兩個複數可以直接進行+、-等運算,但在C++中,直接將+或-用於複數對象是不允許的。有時會希望,讓對象也能通過運算符進行運算。這樣代碼就更簡潔,也容易理解。
例如:
complex_a 和 complex_b 是兩個複數對象,求兩個複數的和,希望的能直接寫成:complex_a + complex_b
這時我們就需要對 +
號運算符進行重載。
02 運算符重載的形式
運算符重載的實質就是函數重載,可以重載為普通函數,也可以重載為成員函數。運算符重載的基本形式如下:
返回值類型 operator 運算符(形參表)
{
...
}
下麵舉個例子,實現對複數對象的 +
和 -
運算符重載:
class Complex // 複數類
{
public:
// 構造函數,如果不傳參數,預設把實部和虛部初始化為0
Complex(double r = 0.0, double i = 0.0):m_real(r),m_imag(i) { }
// 重載-號運算符,屬於成員函數
Complex operator-(const Complex & c)
{
// 返回一個臨時對象
return Complex(m_real - c.m_real, m_imag - c.m_imag);
}
// 列印複數
void PrintComplex()
{
cout << m_real << "," << m_imag << endl;
}
// 將重載+號的普通函數,定義成友元函數
// 目的是為了友元函數能訪問對象的私有成員
friend Complex operator+(const Complex &a, const Complex &b);
private:
double m_real; // 實部的值
double m_imag; // 虛部的值
};
// 重載+號運算符,屬於普通函數,不是對象的成員函數
Complex operator+(const Complex &a, const Complex &b)
{
// 返回一個臨時對象
return Complex(a.m_real + b.m_real, a.m_imag + b.m_imag);
}
int main()
{
Complex a(2,2);
Complex b(1,1);
Complex c;
c = a + b; // 等價於c = operator+(a,b)
c.PrintComplex();
c = a - b; // 等價於 c = a.operator-(b)
c.PrintComplex();
return 0;
}
輸出結果:
3,3
1,1
從上面的例子中,我們可以知道重載為成員函數和普通函數的區別了:
- 重載為成員函數時,參數個數為運算符目數減一。如:
c = a - b;
等價於c = a.operator-(b)
- 重載為普通函數時,參數個數為運算符目數。如:
c = a + b;
等價於c = operator+(a,b)
在上面的代碼中,我把重載 +
號運算符的普通函數,在Complex
複數類中定義成了友元函數,目的是為了友元函數能訪問對象的私有成員,否則會編譯報錯。
03 +號和-號重載函數的返回值和參數表
這裡還有個值得思考的問題:
- 為什麼重載-號和+號運算符函數的返回類型是
Complex
對象而不是Complex &
呢? - 為什麼重載-號和+號的運算符函數的參數表是
const Complex & c
常引用類型而不是Complex c
呢?
// 重載-號運算符,屬於成員函數
Complex Complex::operator-(const Complex & c)
{
// 返回一個臨時對象
return Complex(m_real - c.m_real, m_imag - c.m_imag);
}
首先先說一下參數表為什麼是const Complex & c
常引用類型,首先如果參數表如果普通的對象形式Complex c
,那麼在入參的時候,就會調用預設的賦值(拷貝)構造函數,產生了一個臨時對象,這會增大開銷,所以就採用引用的方式,同時又為了防止引用的對象被修改,所以就定義成了const Complex & c
常引用類型。
再來說一下返回值為什麼是普通Complex
對象,因為本次 - 號和 + 號運算符的函數執行之後,需要返回一個新的對象給到左值。