运算符 的 重载

来源:百度文库 编辑:神马文学网 时间:2024/04/28 05:53:54

1.什么是运算符重载?

所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能。运算符也可以重载。实际上,我们已经在不知不觉之中使用了运算符重载。现在要讨论的问题是:用户能否根据自己的需要对C++已提供的运算符进行重载,赋予它们新的含义,使之一名多用。譬如,能否用“+”
号进行两个复数的相加。在C++中不能在程序中直接用运算符“+”对复数进行相加运算。用户必须自己设法实现复数相加。例如用户可以通过定义一个专门的函数来实现复数相加。

见例1:


通过函数来实现复数相加。
#include
using namespace std;

class Complex //定义Complex类
{
public:
   Complex( ){real=0;imag=0;} //定义构造函数
   Complex(double r,double i){real=r;imag=i;} //构造函数重载
   Complex complex_add(Complex &c2); //声明复数相加函数
   void display( ); //声明输出函数
private:
   double real; //实部
   double imag; //虚部
};
Complex Complex::complex_add(Complex &c2)
{
   Complex c;
   c.real=real+c2.real;

   c.imag=imag+c2.imag;
   return c;

}
void Complex::display( ) //定义输出函数
{
   cout<<"("<

}
int main( )
{

   Complex c1(3,4),c2(5,-10),c3; //定义3个复数对象
   c3=c1.complex_add(c2); //调用复数相加函数
   cout<<"c1 = "; c1.display( ); //输出c1的值
   cout<<"c2 = "; c2.display( ); //输出c2的值
   cout<<"c1+c2 = "; c3.display( ); //输出c3的值
   return 0;
}

运行结果如下:

c1 = (3,4i)
c2 = (5,-10i)
c1+c2 = (8,-6i)
请按任意键继续. . .

 

结果无疑是正确的,但调用方式不直观、太烦琐,使人感到很不方便。能否也和整数的加法运算一样,直接用加号“+”来实现复数运算呢?如c3=c1+c2;编译系统就会自动完成c1和c2两个复数相加的运算。如果能做到,就为对象的运算提供了很大的方便。这就需要对运算符“+”进行重载。

 

2.运算符重载的方法

运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载重载运算符的函数一般格式如下:函数类型operator运算符名称 (形参表列){对运算符的重载处理 }例如,想将“+”用于ComplexleoxpCm类(复数)的加法运算,函数的原型可以是这样的:

 

Complex operator+(Complex& c1,Complex& c2);

 

在定义了重载运算符的函数后,可以说:函数operator+重载了运算符+。为了说明在运算符重载后,执行表达式就是调用函数的过程,可以把两个整数相加也想像为调用下面的函数:
int operator + (inta,intb)

  return (a+b);

}

如果有表达式5+8,就调用此函数,将5和8作为调用函数时的实参,函数的返回值为13。这就是用函数的方法理解运算符。
可以在例1程序的基础上重载运算符“+”,使之用于复数相加。

 

例2 改写例1,重载运算符“+”,使之能用于两个复数相加:

#include
using namespace std;

class Complex
{
public:
   Complex(){ real=0 ; imag=0; }
   Complex(double r , double i){real=r ; imag=i;}
   Complex operator+(Complex &c2); //声明重载运算符的函数
   void display();
private:
   double real;
   double imag;
};
Complex Complex::operator+(Complex &c2) //定义重载运算符的函数
{
   Complex c;
   c.real=real+c2.real;
   c.imag=imag+c2.imag;
   return c;
}

void Complex::display()
{
   cout<<"("<}
int main()
{
   Complex c1(3,4),c2(5,-10),c3;
   c3=c1+c2; //重载后的+用于复数运算,所调用的"+"属于左侧的对象,在这里是c1

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


运行结果与例1相同:

c1 = (3,4i)
c2 = (5,-10i)
c1+c2 = (8,-6i)
请按任意键继续. . .

 

请比较例1和例2,只有两处不同:
(1)在例2中以 operator+ 函数取代了例1中的 complex_addlceoxdpmad 函数,而且只是函数名不同,函数体和函数返回值的类型都是相同的。
(2)在main函数中,以"c3 = c1 + c2;"取代了例1中的“c3 = c1.complex_add(c2);”。在将运算符 + 重载
类的成员函数后,C++编译系统将程序中的表达式c1 + c2解释为c1.operator+(c2) ,其中c1和c2是Complex
类的对象,即c1的运算符重载函数operator+(Complex &c2)把c2作为实参来调用,进行求值,得到两个复数之和。

 

虽然重载运算符所实现的功能完全可以用函数实现,但是使用运算符重载能使用户程序易于编写、阅读和维护。在实际工作中,类的声明和类的使用往往是分离的。假如在声明Complex类时,对运算符+,-,*,/都进行了重载,那么使用这个类的用户在编程时可以完全不考虑函数是怎么实现的,放心大胆地直接使+,-,*,/进行复数的运算即可,十分方便。


对上面的运算符重载函数operator+还可以改写得更简练一些:
Complex Complex::operator + (Complex &c2)
{
  return Complex(real + c2.real , imag + c2.imag);
}


需要说明的是:
运算符被重载后,其原有的功能仍然保留,没有丧失或改变。

 

通过运算符重载,扩大了C++已有运算符的作用范围,使之能用于类对象。
运算符重载对C++有重要的意义,把运算符重载和类结合起来,可以在C++程序中定义出很有实用意义而使用方便的新的数据类型。运算符重载使C++具有更强大的功能、更好的可扩充性和适应性,这是C++最吸引人的特点之一。

 

3.重载运算符的规则

(1)C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。

(2)C++中绝大部分的运算符允许重载。不能重载的运算符只有5个:
      (成员访问运算符)
.*      (成员指针访问运算符)
::      (域运算符)
sizeof  (长度运算符)
     (条件运算符)
前两个运算符不能重载是为了保证访问成员的功能不能被改变,域运算符和sizeof运算符的运算对象是类型而不是变量或一般表达式,不具重载的特征。
(3)重载不能改变运算符运算对象(即操作数)的个数
(4)重载不能改变运算符的优先级别
(5)重载不能改变运算符的结合性
(6)重载运算符的函数不能有默认的参数,否则就改变了运算符参数的个数,与前面第(3)点矛盾。
(7)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。也就是说,参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。