以向量運算為例,總結運算符重載

語言: CN / TW / HK

感覺面向對象掌握不是太好,第一個問題就是重載不太熟練。今天又好好寫了一個上課講過的題目,回來看了看覺得有點收穫,寫一下總結一下經驗。

#include <iostream>
using namespace std;
class intMyVector{
   
   
	public:
		intMyVector(int count){
   
   
			n=count;//儲存向量位數
			p=new int[n];//開闢空間儲存輸入的向量
		}
		intMyVector(const intMyVector& v){
   
   //複製構造函數
			n=v.n;
			p=new int[n];
			for(int i=0;i<n;i++) p[i]=v.p[i];
		}
		friend ostream &operator <<(ostream& ,const intMyVector&);//由於輸出時不希望輸出的值在這一步發生改變,因此使用const
		friend istream &operator >>(istream& ,intMyVector&);//輸入的時候肯定會改變原來的值,所以沒有const
		intMyVector operator + (const intMyVector&);//const同重載輸出
		intMyVector& operator = (const intMyVector&);//const同重載輸出
		~intMyVector(){
   
   delete[]p;cout<<"destruct"<<endl;}
	private:
		int n;//向量維數
		int *p;//指向儲存向量空間的指針。
}


int main(){
   
   
	int n;
	cin>>n;
	intMyVector a(n),c(n+1);
	cin>>a;//調用>>重載
	c=a;//調用=重載
	intMyVector b(a);//調用複製構造函數
	cout<<a+b+c;//調用<<輸出重載以及+重載
	return 0;
}

intMyVector intMyVector::operator + (const intMyVector& b){
   
   
	intMyVector A;//創建中間變量由於返回運算結果
	for(int i=0;i<n;i++){
   
   
		A.p[i]=p[i]+b.p[i];
	}
	return A;
}

intMyVector& intMyVector::operator =(const intMyVector& b){
   
   //這一個重載函數的解釋寫在下面
 	n=b.n;
 	delete[] p;
 	p=new int[n];
 	for(int i=0;i<n;i++){
   
   
  	p[i]=b.p[i];
 	}
 	return *this;
}

istream& operator >> (istream & input,intMyVector& v){
   
      
    	for(int  i=0;i<v.n;i++) input>>v.p[i];
   	return input;
}

ostream& operator << (ostream&    output,  const intMyVector& v){
   
   
	output<<"["; 
    	for(int i=0;i<(v.n-1);i++) output<<v.p[i]<<",";
        output<<v.p[v.n-1]<<"]"<<endl; 
    	return output; 
} 

解釋一下 “=” 重載函數:

首先為什麼要 n=b.n ?原因可以看一下main函數裏面的c,c的維數是n+1,a的維數是n,直接享加肯定會有問題。所以這個地方的重載要實現的不僅僅是c=a數據的等於,也有維數的統一。

delete[] p 這個是因為在構造c(n+1)的時候,已經開闢了一個n+1空間的p,維數統一的話就要把原來構建的空間刪了重新構造 p=new int[n];後面就是簡單的對應位等於起來就好了。

return *this一開始沒想明白,但是仔細想想,好像除了this也沒有東西可以返回了。況且this本就可以指向c這個類。

稍微總結一下就有幾個點

friend ostream &operator <<(ostream& ,const intMyVector&)
friend istream &operator >>(istream& ,intMyVector&);
intMyVector operator + (const intMyVector&);
intMyVector& operator = (const intMyVector&);


輸入輸出的重載需要在前面加上friend來允許訪問私有類,畢竟它們倆本身也不是intMyVector裏面的成員函數(寫的時候沒有 intMyVector::)

&用於返回指針指向的成員,比如“=”重載就是用來返回*this指針

intMyVector operator + (const intMyVector&);我寫的時候產生了一個臨時變量,所以析構的時候這個臨時變量也會析構掉,如果想要減少析構次數,就在類裏面定義一個全局變量,這樣在最後只會對這個全局變量析構了。但是改用全局變量的話,函數也要改一下。

首先在類外加一個 intMyVector A(3);這裏的“3”寫什麼無所謂,待會就會知道
然後對+的重載也要有改寫

intMyVector& intMyVector::operator + (const intMyVector& b){
   
   //這裏的&一定要加
 	A.n=b.n;//這就是為什麼3是什麼無所謂,反正都得刪了重新弄出一個適合維度的全局變量A。
 	delete[] A.p;//這裏就和“=”的重載比較相似
 	A.p=new int[A.n];
 	for(int i=0;i<n;i++){
   
   
  		A.p[i]=p[i]+b.p[i];
 	}
 	return A;
} 

從“+”的重載基本就可以自推出-,*,/的重載了。

關於什麼時候用&,我總結的是:看返回的對象,返回自身的話就&,如果建立一個臨時變量就不用加&。
以自加的重載為例(與上題無關):

intMyVector &operator++()//返回自加之後的數
    {
   
   
        n++;
        return *this;//自加後返回自身
    }
    intMyVector operator++(int)//返回自加前的數
    {
   
   
        TextClass temp(n);
        n++;
        return temp;//自加結束後返回自加前的數,只能通過局部變量保存之前的數,return這個局部變量
    }

至此,重載基本上也就這些(?)