以向量运算为例,总结运算符重载

语言: 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这个局部变量
    }

至此,重载基本上也就这些(?)