运算符重载

 

一、概述

1、运算符重载的实质:

运算符重载的实质就是函数重载。在实现过程中,首先把指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参,然后根据实参的类型来确定需要调用的函数,这个过程是在编译过程中完成的。

2、运算符重载的规则:

(1)C++中的运算符除了少数几个以外,全部可以重载,而且只能重载已有的运算符,不允许用户自己定义新的运算符。

(2)重载之后运算符的优先级、结合性都不会改变。

(3)重载不能改变操作数的个数。

(4)重载运算符的函数不能有默认的参数,否则就改变了运算符的个数,与(3)矛盾。

(5)重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少要有一个是类对象或类对象的引用,也就是说,参数不能全部是C++的标准类型。

(6)运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数。

(7)运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。

3、C++不可以重载的运算符:

'.'(成员访问运算符)

'::'(域运算符)

'.*'(成员指针访问运算符)

'? :'(条件运算符)

'sizeof'(长度运算符,技术上可以看做运算符),只有这五种运算符是不能重载,其余都可以重载。

二、实现

运算符的重载形式有两种:重载为类的成员函数和重载为类的友元函数。

1、运算符重载为类的成员函数,语法形式如下:

    函数类型 operator 运算符(形参表)

    {

       函数体

    }

2、运算符重载为类的友元函数,语法形式如下:

    friend 函数类型 operator 运算符(形参表)

    {

      函数体

    }

3、举例:

分别用两种方式实现time类,用来保存时间(时、分、秒),通过重载操作符“+”实现两个时间的相加。

(1)用类的成员函数来实现:

/*例1:定义一个Time类用来保存时间(时、分、秒),通过重载操作符“+”实现两个时间的相加。*/

    /* IDE:VC6.0 */

    #include <stdio.h>

    class Time

    {

    public:

      Time(){ hours=0;minutes=0;seconds=0;} //无参构造函数

      Time(int h, int m,int s) //重载构造函数

      {

               hours=h; minutes=m; seconds=s;

      }

      Time operator +(Time&); //操作符重载为成员函数,返回结果为Time类

      void gettime();

    private:

      int hours,minutes,seconds;

    };

    Time Time::operator +(Time& time)

    {

    int h,m,s;

    s=time.seconds+seconds;

    m=time.minutes+minutes+s/60;

    h=time.hours+hours+m/60;

    Time result(h,m%60,s%60);

    return result;

    }

    void Time::gettime()

    {

    printf("%d:%d:%d\n",hours,minutes,seconds);

    }

    int main( )

    {

    Time t1(8,51,40),t2(4,15,30),t3;

    t3=t1+t2;

    t3.gettime();

    return 0;

    }          

         输出结果为:

    13:7:10

(2)用类的友元函数来实现:

/*例2:对例1进行修改,采用操作符重载为友元函数实现。*/

    /* IDE:VC6.0 */

    #include <stdio.h>

    class Time

    {

    public:

      Time(){ hours=0;minutes=0;seconds=0;} //无参构造函数

      Time(int h, int m,int s) //重载构造函数

      {

               hours=h; minutes=m; seconds=s;

      }

      friend Time operator +(Time&,Time&); //重载运算符为友元函数形式。

                                                                   //友元不是类成员,所以这里要用两个参数,返回这两个参数的和。

      void gettime( );

    private:

      int hours,minutes,seconds;

    };

       Time operator +(Time& time1,Time& time2)

    {

    int h,m,s;

    s=time1.seconds+time2.seconds;              //计算秒数

    m=time1.minutes+time2.minutes+s/60;      //计算分数

    h=time1.hours+time2.hours+m/60;           //计算小时数

    Time result(h,m%60,s%60);

    return result;

    }

       void Time::gettime( )

    {

    printf("%d:%d:%d\n",hours,minutes,seconds);

    }

       int main( )

    {

    Time t1(8,51,40),t2(4,15,30),t3;

    t3=t1+t2; //调用友元函数

    t3.gettime( );

       return 0;

       }  

          输出结果为:

   13:7:10

 

三、一元运算符重载

类的单目运算符可重载为一个没有参数的非静态成员函数或者带有一个参数的非成员函数,参数必须是用户自定义类型的对象或者是对该对象的引用。

在C++中,单目运算符有++和--,它们是变量自动增1和自动减1的运算符。在类中可以对这两个单目运算符进行重载。

如同“++”运算符有前缀和后缀两种使用形式一样,“++”和“--”重载运算符也有前缀和后缀两种运算符重载形式,以“++”重载运算符为例,其语法格式如下:

    <函数类型> operator ++();           //前缀运算

<函数类型> operator ++(int);   //后缀运算

注:C++约定,如果在自增或自减运算符重载函数中,增加一个int型形参,就是后置自增、自减运算符函数。

    使用前缀运算符的语法格式如下:

++<对象>;

使用后缀运算符的语法格式如下:

<对象>++;

/*例3:友元函数重载示例,Increase的定义。*/

    #include <stdio.h>

    class Increase{

    public:

           Increase(int x):value(x){}

           friend Increase & operator++(Increase & );            //前增量

           friend Increase operator++(Increase &,int);            //后增量

           void display(){ printf("the value is %d \n", value); }

    private:

           int value;

    };

    Increase & operator++(Increase & a)

    {

           a.value++;                      //前增量

           return a;                         //再返回原对象

    }

    Increase operator++(Increase& a, int)

    {

           Increase temp(a);        //通过拷贝构造函数保存原有对象值

           a.value++;                 //原有对象增量修改

           return temp;              //返回原有对象值

    }

    int main()

    {

           Increase n(20);

           n.display();

           (n++).display();          //显示临时对象值

           n.display();                 //显示原有对象

           ++n;

           n.display();

           ++(++n);

           n.display();

           (n++)++;                 //第二次增量操作对临时对象进行

           n.display();

           return 0;

    }

        此程序的运行结果为:

    the value is 20

    the value is 20

    the value is 21

    the value is 22

    the value is 24

    the value is 25

四、二元运算符重载

1、对于双目运算符,一个运算数是对象本身的数据,由this指针给出,另一个运算数则需要通过运算符重载函数的参数表来传递。下面分别介绍这两种情况。

2、对于双目运算符B,如果要重载B为类的成员函数,使之能够实现表达式“oprd1 B oprd2”,其中oprd1为A类的对象,则应当把B重载为A类的成员函数,该函数只有一个形参,形参的类型是oprd2所属的类型。

经过重载之后,表达式oprd1 B oprd2就相当于函数调用“oprd1.operator B(oprd2)”。

       /*例4:设计一个点类Point,实现点对象之间的各种运算。*/
    #include <stdio.h>
    #include <iostream.h>
       class Point
    {
              int x,y;
    public:
    Point() {x=y=0;}
    Point(int i,int j) {x=i;y=j;}
    Point(Point &);
    ~Point() {}
       void offset(int,int);    //提供对点的偏移
    void offset(Point);         //重载,偏移量用Point类对象表示
    bool operator==(Point);     //运算符重载,判断两个对象是否相同
       bool operator!=(Point); //运算符重载,判断两个对象是否不相同
    void operator+=(Point);     //运算符重载,将两个点对象相加
    void operator-=(Point);     //运算符重载,将两个点对象相减
    Point operator+(Point);     //运算符重载,相加并将结果放在左操作数中
    Point operator-(Point);     //运算符重载,相减并将结果放在左操作数中
    int getx() {return x;}
    int gety() {return y;}
       void disp()
    {
               cout<<"(" <<x <<"," <<y <<")" <<endl;
    }
    };
    Point::Point(Point &p)
    {
    x=p.x;y=p.y;
    }
    void Point::offset(int i,int j)
    {
    x+=i;y+=j;
    }
    void Point::offset(Point p)
    {
    x+=p.getx();y+=p.gety();
    }
    bool Point::operator==(Point p)
    {
             if(x==p.getx() &&y==p.gety())
                    return 1;
             else
                    return 0;
    }
    bool Point::operator!=(Point p)
    {
             if(x!=p.getx() ||y!=p.gety())
               return 1;
             else
         return 0;
    }
    void Point::operator+=(Point p)
    {
             x+=p.getx();y+=p.gety();
    }
    void Point::operator-=(Point p)
    {
             x-=p.getx();y-=p.gety();
    }
    Point Point::operator+(Point p)
    {
             this->x+=p.x; this->y+=p.y;
    return *this;
    }
    Point Point::operator-(Point p)
    {
             this->x-=p.x; this->y-=p.y;
    return *this;
    }
       int main()
    {
      Point p1(2,3),p2(3,4),p3(p2);
    printf("1:");
    p3.disp();
    p3.offset(10,10);
    printf("2:");
p3.disp();
       printf("3:\n", p2==p3);
    printf("4:\n", p2!=p3);
       p3+=p1;
    printf("5:");
    p3.disp();
    p3-=p2;
      printf("6:");
    p3.disp();
    p3=p1+p3;               //先将p1+p3的结果放在p1中,然后赋给p3
    printf("7:");
    p3.disp();
    p3=p1-p2;
    printf("8:");

    p3.disp();
     return 0;
    }
        运行结果:
    1:(3,4)
    2:(13,14)
    3:
    4:
    5:(15,17)
    6:(12,13)
    7:(14,16)
    8:(11,12)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值