运算符重载


一.运算符重载基本规则

1.运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同的行为。
2.一般来讲,重载的功能应当与原有功能相似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。
3.运算符的重载形式有两种,分别是重载为类的非静态成员和重载为非成员函数,下面我们也将从两种下手开始讨论。
它们的一般语法形式为:

返回类型 operator 运算符(形参表) {
函数体  

}

注:返回类型指定了重载运算符的返回类型,也就是运算结果类型。

二.加减法重载

说明:重载为类的成员函数时,第一个操作数会被作为函数调用的目的对象,因此无法出现在参数表中。即oprd1 B oprd2,其中oprd1为A类的对象,则应当把B重载为A类的成员函数,该函数只有一个形参,形参的类型是oprd2所属的类型,即oprd1 B oprd2相当于oprd1.operator B(oprd2)

(一).加减法重载为成员函数


#include "pch.h"
#include <iostream>

using namespace std;

class Complex 
{
public:
	Complex(double r=0.0,double i=0.0):real(r),imag(i){}
	Complex operator+(const Complex &c2)const;
	Complex operator-(const Complex &c2)const;//用对象作为参数时,用引用或者传地址,一般用引用
	void display()const 
	{
		cout << "(" << real << "," << imag << ")" << endl;
	}
private:
	double imag, real;//复数的虚部和实部
};

Complex Complex::operator+(const Complex &c2)const
{
	return Complex(real + c2.real, imag + c2.imag);//创建了一个临时无名对象作为返回值
}

Complex Complex::operator-(const Complex &c2)const
{
	return Complex(real - c2.real, imag - c2.imag);//创建了一个临时无名对象作为返回值
}

int main()
{
	Complex c1(5, 4), c2(2, 3), c3;
	cout << "c1="; c1.display();
	cout << "c2="; c2.display();
	c3 = c1 + c2;
	cout << "c3=c1+c2="; c3.display();
	c3 = c1 - c2;
	cout << "c3=c1-c2="; c3.display();
	return 0;
}

运行结果:


  • 修改1:由上面写的说明,我们来对说明进行证明,我们修改代码如图



我们运行可以正常运行,证明了我们上面的说明。

  • 修改2:我们定义一个新的Complex类型的c,对它进行以下操作



注:这里我们看到整数5加到了原来c1的5上,可能有的人会想为什么不在c1的4上也加上,这里我们需要理解一下复数(a+bi)+(c+di)=(a+c)+(b+d)i。
当我们加上5的时候相当于让实部为5,让虚部为0了即让d为0了。

  • 修改3:



我们发现也是正确的,那如果我们把它写成c=5+c1又会不会对呢?

  • 修改4:



我们发现程序报错,说明这样是不对的,那我们怎样解决它呢?这里就需要我们把运算符重载为非成员函数了。那这又是为什么呢?



(二).加减法重载为非成员函数


#include "pch.h"
#include <iostream>

using namespace std;

class Complex 
{
public:
	Complex(double r=0.0,double i=0.0):real(r),imag(i){}
	friend Complex operator+(const Complex &c1,const Complex &c2);
	friend Complex operator-(const Complex &c1,const Complex &c2);//用对象作为参数时,用引用或者传地址,一般用引用
	void display()
	{
		cout << "(" << real << "," << imag << ")" << endl;
	}
private:
	double imag, real;
};

Complex operator+(const Complex &c1, const Complex &c2)
{
	return Complex(c1.real + c2.real, c1.imag + c2.imag);//创建了一个临时无名对象作为返回值
}

Complex operator-(const Complex &c1, const Complex &c2)
{
	return Complex(c1.real - c2.real, c1.imag - c2.imag);//创建了一个临时无名对象作为返回值
}


int main()
{
	Complex c1(5, 4), c2(2, 3), c3,c;
	cout << "c1="; c1.display();
	cout << "c2="; c2.display();

	c3 = c1 + c2;
	cout << "c3=c1+c2="; c3.display();
	c3 = c1 - c2;
	cout << "c3=c1-c2="; c3.display();

	
	c =5+ c1 ;
	cout << "c=c1+5="; c.display();

	return 0;
}

运行截图:


我们注意看这里就实现了c=5+c1。

那我们思考为什么以非成员函数形式重载,就可以实现c=5+c1呢?
(教材的315页对此进行了详细解释)因为Comlpex的构造函数使得实数可以隐含转换为Complex类型,而以成员函数重载的时候,左操作数是调用成员函数的目的对象,它不会被隐含转化,只有右操作数是函数的参数,可以隐含转化为Complex类型。



三.“++”的重载


(一)“++”的重载为成员函数

#include "pch.h"
#include <iostream>

using namespace std;

class Complex 
{
public:
	Complex(double r=0.0,double i=0.0):real(r),imag(i){}
	Complex &operator++();
	Complex operator++(int);//后++
	void display()
	{
		cout << "(" << real << "," << imag << ")" << endl;
	}
private:
	double imag, real;
};

Complex &Complex::operator++()
{
	imag++;
	real++;//先++
	return *this;
}

Complex Complex::operator++(int)
{
Complex a = *this;//this指向的原来的对象,先把自己的值弄出来,在对自己++
++(*this);
return a;
}


int main()
{
	Complex a(1, 2),b,d;
	a.display();

	b = ++a;
	cout << "++a="; b.display();
	d = a++;
	cout << "a++="; d.display();

	cout << "a++后"; a.display();

	return 0;
}

运行截图:


这里我们注意看先++和后++的区别,在代码的最后我们也可以看到,后++的实现。



(二)“++”的重载为非成员函数


#include "pch.h"
#include <iostream>

using namespace std;

class Complex 
{
public:
	Complex(double r=0.0,double i=0.0):real(r),imag(i){}

	friend Complex operator++(Complex &c);//前++
	friend Complex operator++(Complex &c,int);//后++

	void display()
	{
		cout << "(" << real << "," << imag << ")" << endl;
	}
private:
	double imag, real;
};

Complex operator++(Complex &c)//前++
{
    c.imag++;
	c.real++;
	return c;
}

Complex operator++(Complex &c,int)//后++
{
Complex a = c;
++c;
return a;
}


int main()
{
	Complex a(1, 2),b,d;
	a.display();

	b = ++a;
	cout << "++a="; b.display();
	d = a++;
	cout << "a++="; d.display();

	cout << "a++后"; a.display();

	return 0;
}

运行截图:


这里我们注意我们是通过传值的方式传递参数的,假如我们进行如下的修改

  • 修改1:


运行结果:


我们观察运行结果发现出现了错误,原因是这个函数的形参是对象,是通过传值的方式传递参数的,函数体内对形参的所有修改都无法传到函数体的外面。而形参是对象的引用时,是通过传地址的方式传递参数的。

posted on 2019-10-27 10:01  咬一口云朵软绵绵  阅读(175)  评论(0编辑  收藏  举报