白话文说c++ 操作符重载

前言
c++操作符重载的背景主要是原有的操作符+ - += 等只能运算基本数据类型 int double这些,但是实际中我们经常遇到很多自定义的类型,比如复数 结构体等,比如要计算1+2i 与2+3i这两个复数的和或者比大小,计算机就没有直接的方法进行计算,这时候,运算符重载起到了很大的作用,其实我们也可以自己定义一个add(complex a,complex b)进行计算,但是通过运算符重载,我们可以利用+号实现add()这个函数功能,类似,我们还可以比较a与b的大小。此外,我们也可以比较两个结构体的大小,规则由你自己定。
运算符重载可以重载为友元函数或者成员函数,当然一些运算符比如流运算符<< ,>>只能重载为友元,理由可以看看其他大牛的解读,废话不多说,直接上例子。

以下是一个复数类

class complex
{
	double re,im;
	public:
		complex();
		complex(double re,double im);
		complex(const complex& another);
		~complex();
		complex operator+(const complex& another);
		complex& operator+=(const complex& another);
		bool operator<(const complex& another);
		friend ostream& operator<<(ostream& os,const complex& a);
		friend istream& operator>>(istream& in, complex& a);
		friend complex& operator+(const complex& a,const complex& b);
};

我只拿了几个有代表性的例子
1.complex operator+( complex another);
friend complex& operator+(const complex& a,const complex& b);
这是重载+运算符,第一个是成员函数,第二个是友元函数,可能你们已经看出来了有些是引用,有些不是引用,下面一一讨论参数和返回值到底要不要用引用。

参数是否需要引用,说到引用,可以理解为别名,也可以理解为指针常量, complex * const p = &obj,p就是一个指针常量,也就是指针指向的地址是固定的,即使在下一句再写 p = &obj,也会报错,引用也一样,complex& p=obj,p和obj也是绑定在一起的,改变两者中任一个值,另外一个也会改变,当然,析构任意一个,另外一个也被析构了,并且只调用了析构函数一次,不是两次。所以引用型变量作为参数时不是进行值传递,我觉得便于记忆可以理解为将对象本身传进去了,而如果不用引用,将会是进行值传递,编译器会自动调用拷贝构造函数,创建一个临时对象,而通过引用型变量将不会调用构造函数,更高效。但有一个问题,如果传引用不小心被改变了怎么办呢?我们并不想改变原有对象的值,所以加一个const,防止对象被改变。附上测试图

int main(int argc, char** argv) {
	complex a(1,2),b(3,4);
	complex c;
	c = a.operator+(b); 
	cout<<c;
	return 0;
}
complex complex::operator+( complex another){
complex res;
res.im = this->im+another.im;
res.re = this->re+another.re;
return res;

}

在这里插入图片描述

一共调用了5次构造函数分别是创建对象a,b,c,res时和进行值传递时调用了拷贝构造函数,所以参数采用引用可以更加高效,省去了拷贝构造临时变量和析构临时变量的时间,不要忘记加const。

而返回值是否需要引用就是要根据返回的对象是否是在该函数创建的临时变量,上文说到引用型变量会和其绑定的变量一同析构,如果返回一个临时变量的引用,而该临时变量当该函数运行完会被析构,所以返回它的引用自然就是一个垃圾值了,而如果返回的是参数的引用,当该函数运行完时,该参数并不会被析构,所以返回它的引用是没问题的。当然也可以仅仅返回值,只不过这时又会调用拷贝构造函数,效率不高。

complex complex::operator+( const complex& another){
complex res;
res.im = this->im+another.im;
res.re = this->re+another.re;
return res;

}//res是在该函数体内创建的对象,只能返回值,因为离开函数体,res就会被析构,如果返回引用将会是一个垃圾数据

complex& complex::operator+=(const complex& a){
	this->im += a.im;
	this->re += a.re;
	return *this;
}//可以返回引用型,省去了拷贝构造,更加高效 main函数调用时可以用a+=b或者a.operator+=(b)调用 两者结果一致

部分源码

class complex
{
	double re,im;
	public:
		complex();
		complex(double re,double im);
		complex(const complex& another);
		~complex();
		complex operator+( const complex& another);
		complex& operator+=(const complex& another);
		complex operator-(const complex& another);
		complex operator*(const complex& another);
		bool operator<(const complex& another);
		bool operator>(const complex& another);
		friend complex operator-(const complex& a,const complex& b); 
		friend ostream& operator<<(ostream& os,const complex& a);
		friend istream& operator>>(istream& in, complex& a);
		friend complex& operator+(const complex& a,const complex& b);
		friend complex& operator+=(complex& a,const complex& b);
		friend complex operator*(complex& a,const complex&b);
};
complex::complex(){
	std::cout<<"complex():"<<endl;
}
complex::complex(double re,double im){
	cout<<"complex(re,im):"<<endl;
	this->im = im;
	this->re = re;
}
complex::~complex(){
	cout<<"~complex()"<<endl;
}
complex::complex(const complex& another){
	cout<<"copy constructor!"<<endl;
	this->im = another.im;
	this->re = another.re;
}
//complex operator+(const complex& another);成员函数重载+ 
complex complex::operator+( const complex &another){
	complex res;
	res.im = this->im+another.im;
	res.re = this->re+another.re;
	return res;
}

//friend complex operator+(const complex& a,const complex& b);友元函数重载+ 
complex& operator+(const complex&a,const complex& b){
	complex res;
	res.im = a.im+b.im;
	res.re = a.re+b.re;
	return res;
}

//complex operator-(const complex& another);成员函数重载- 
complex complex::operator-(const complex& another){
	complex res;
	res.im = this->im-another.im;
	res.re = this->re-another.re;
	return res;
}
//friend complex operator-(const complex& a,const complex& b); 友元函数重载- 
complex operator-(const complex& a,const complex& b){
	complex res;
	res.im = a.im-b.im;
	res.re = a.re-b.re;
	return res;
}
//friend ostream& operator<<(ostream& os,const complex& a);友元函数重载输出流 
ostream& operator<<(ostream& os,const complex& a){
	os<<"("<<a.re<<","<<a.im<<"i)"<<endl;
	return os;
}
//	friend istream& operator>>(istream& in, complex& a); 友元函数重载输入流 
istream& operator>>(istream& in,complex& a){
	in>>a.re>>a.im;
	return in;
}
//complex& operator+=(const complex& another); 成员函数重载+= 
complex& complex::operator+=(const complex& a){
	this->im += a.im;
	this->re += a.re;
	return *this;
}
//friend complex& operator+=(complex& a,const complex& b);友元函数 重载+= 
complex& operator+=(complex& a,const complex& b){
	a.im += b.im;
	a.re += b.re;
	return a;
}
//complex operator*(const complex& another); 成员函数重载* 
complex complex::operator*(const complex& another){
	complex res;
	res.re = this->re*another.re-this->im*another.im;
	res.im = this->re*another.im+this->im*another.re;
	return res;
}

//friend complex operator*(complex& a,const complex&b); 友元函数重载* 
complex operator*(const complex& a,const complex& b){
	complex res;
	res.re = a.re*b.re-a.im*b.im;
	res.im = a.re*b.im+a.im*b.re;
	return res;
}
//自定义比较虚数大小
bool complex::operator<(const complex& another){
	return this->re>another.re;
}
bool complex::operator>(const complex& another){
	return this->re<another.re;
}

猜你喜欢

转载自blog.csdn.net/qq_42673507/article/details/84843429