现在的位置: 首页 > 综合 > 正文

运算符重载

2013年08月04日 ⁄ 综合 ⁄ 共 3810字 ⁄ 字号 评论关闭

2010-11-27运算符重载(一)

        一般说来,c++内定义类型(例如,int,char,float等)的操作用运算符来表示,其调用形式是表达式。用户定义类型的操作则用函数来表示,对它采用显式调用。为了使用户定义的类型与内定义类型一致,也允许用户定义类型使用运算符来表示操作。这种一致性还表现在可以为用户定义类型提供初始化函数,赋值函数以及转换规则等。如果利用重载的运算符来增添新的类型,例如复数,集合等,这些用户定义的新类型可以象内部定义的类型一样来使用。对c++各种运算符的重新定义,既运算符的重载
  
假设定义了一个复数类,它可以将两个复数相加,例如:
class comlpex{
     private:
        double epart; //
复数的实部
        double ipart; //
复数的虚部
     public :
        complex()
        { 
               rpart+ipart+0.0; //
缺省构造函数
        }
        complex(double rp,double ip)
        {
               rpart=rp;
               ipart=ip;
        }
       complex add(const complex&com)
       {
                 complex temp;
                 temp.rpart=com.rpart+rpart;
                 temp.ipart=com.ipart+ipart;
                 return temp;
       }       
};
现在,就可以用它来进行两复数的加法运算了:
      complex a(10,7),b(3,5);
      complex c=a.add(b); //
a+b
这种加法运算采用函数调用的形式,并不直观。我们希望能和整数或浮点数一样,采用+表达式来实施运算,为此,需要重载+运算符函数。运算符函数的名字是operator关键字,再接着重载的运算符。他的返回值和参数与普遍函数相同。现在,可以重新定义复数的加法:
class complex
{
   //....
   public: 
         complex operator+(const complex&com)
         { 
         complex temp(rpart+com.rpart,ipart+com.ipart);
              return temp;
         }
  //...
};
运算符函数operator+被定义为公有的,以便程序的其他函数能使用它,在定义了函数之后,就可以象在内定义类型上一样,对复数对象用+表达式实施运算,例如:
     complex 1(10,7),b(3,5),c;
     c=a+b
c++
编译器把表达式a+b解释为函数调用a.operator+(b).在调用它时,operator+成员函数首先创建一个临时的complex对象temp,然后把出现在加法表达式中的两个复数之和暂存其内,最后将这个临时对象返回.
   
重载运算符与重载一般函数的区别
   
区别主要是在参数的个数上,c++的运算符所能操作的操作数的个数的个数是规定好的。在重载二元运算符时只能指定两个参数,而重载一元运算符时只能指定一个参数。在重载函数时,可以指定任意的返回类型,甚至可以指定void类型作为返回类型,因为c++允许反调用函数而可以不使用函数的返回值。但c++的运算符是用在表达式中,一个运算符的运算结果要供别的运算符使用,因此任何运算符都指定有非void类型的返回类型。

    类运算符与友员运算符的选取
   
一般而言,对于二元运算符,将它重载为一个友员运算符比重载为一个成员运算符要便于使用。作为一个友员函数,这个运算符不要求第一个参数一定为某个类的对象。一元运算符重载为一个成员函数最恰当,重载为友员也可以。但若将增1或减1运算符重载为友员运算符,则要使用引用参数。

注:赋值运算符不能重载为友员运算符

实 例(1)
class X
{
    public:
          int i;
};

X operator+(const X& x1,const X& x2)
{
    X temp;
    temp.i=x1.i+x2.i;
}


由于操作符的重载,使以下的运算合法

X x1,x2,x3; x1=x2+x3;

 

用成员函数重载运算符 

(1)运算符成员函数只能定义运算符的含义,不能改变运算符的优先级和结合顺序.例如,不论按何种方式重载运算符,a+b*c始终是先乘后加;而a=b=c也要先做b=c,然后,再对a赋值.

   (2)运算符重载时,不能改变其目数.例如,任何企图把%定义为单目运算符,或把!定义为双目运算符的做法都会出错.

 (3)运算符函数即可在中定义,也可以在类外定义.在类外定义时,它至少应有一个相应类的参数.

(4)对于双目运算符@当它用作成员函数时,只带一个参数(另一个运算符有调用它的对象给出),此时aa@bbaa.operator@(bb)等价,当他用作外部函数时,带有两个参数(分别说明两个运算数),此时aa @bbaa.operator@(aa,bb)等价

(5)对于单目前缀运算符@当它用作成员函数时,不必带参数(运算符就是调用它的对象),此时@aaaa.operator@()等价,当它用作外部函数时,带有一个参数(分别说明两个运算数),此时@aaoperator@(aa)等价

(6)对于单目后缀运算符@,当它用作成员函数时,应该带一个int参数(此参数一般不会使用,仅仅是为了把它同单目前缀运算符区分开),此时aa@aa.operator@(int)等价,当它用作外部函数时,他应该带有两个参数,第一个是相应类的参数,第二个是int参数(也是用它来区分前后缀运算符),此时@aaoperator@(aa,int)等价.

(7)无论是在类中定义的运算符成员函数,还是在类外定义的运算符函数,都可以进行重载。也就是说可以定义多个同名的运算符函数。但其参数类型应有差别,否则会产生二义性。

(8)用户可重载已有的运算符,但不能定义自己的运算符,因为这常常会带来二义性,假设自定义**,以便进行乘方运算,编译器将无法确定它是按左结合(象fortran中那样),还是按右结合(象algol中一样);也无法确定表达式a**b是被当作a*(*b)还是a**b.

(9)编译器预定义了=(赋值)&(取地址)(顺序)这三种运算符,不必重载就可以使用它们。如果要限制外部函数对它的使用,可以把它们声明为私有的.

实 例(2)
//******************************

//***  用成员函数重载运算符  ***

//******************************

 

#include <iostream.h>

 

class Complex

{

public:

     Complex()

     {

        real = 0;

        imag = 0;

     }

 

     Complex(double r, double i)

     {

        real = r;

        imag = i;

     }

 

     Complex operator + (Complex& c);

     Complex operator - (Complex& c);  //二元减

     Complex operator - ();            //一元减

     void print();

 

private:

     double real;

     double imag;

};

 

Complex Complex::operator + (Complex& c)

{

     double r = real + c.real;

     double i = imag + c.imag;

   

     return Complex(r, i);

}

 

Complex Complex::operator - (Complex& c)

{

     double r = real - c.real;

     double i = imag - c.imag;

 

     return Complex(r, i);

}

 

Complex Complex::operator - ()

{

     return Complex(-real, -imag);

}

 

void Complex::print()

{

     cout << "(" << real << ", " << imag << ")" << endl;

}

 

int main()

{

     Complex a(5, 4), b(1, 7);

     Complex c(0, 0);

     c = a + b;

     c.print();

     c = a - b;

     c.print();

     c = -b;

     c.print();

 

     return 0;

}

  

用成员函数重载运算符称为类运算符。这种重载运算符函数的语义可表示为<对象>.operator<一元运算符>()<对象1>.operator<二元运算符>(对象2)。前者可解释为给当前对象发送一个进行一元运算的消息;后者可解释为给当 前对象发送一个与对象

抱歉!评论已关闭.