运算符重载
一.运算符重载基本规则
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:
运行结果:
我们观察运行结果发现出现了错误,原因是这个函数的形参是对象,是通过传值的方式传递参数的,函数体内对形参的所有修改都无法传到函数体的外面。而形参是对象的引用时,是通过传地址的方式传递参数的。