以向量運算為例,總結運算子過載

語言: 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這個區域性變數
    }

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