C++系列(运算符重载)

所谓运算符重载,就是给原有运算符赋予新的功能比如说,加好(+)是用来做两个数字相加操作的(如:1+1=2),但是,我们往往用加号来让两个字符串作拼接(如:慕+课=慕课),那么,这个时候就是给加号做了运算符的重载。我们来看一个常见的例子:

在这个例子当中,我们就使用了加号去连接多个字符串,使其拼接成一个字符串,而且,我们在打印的时候,也可以将拼接好的字符串直接打印出来,那么这个字符串就进行了多个运算符的重载(加号运算符做了重载,输出运算符也做了重载,等号运算符也做了重载)。那么,问题是:这些重载究竟是怎么做的呢?后续课程为大家一一讲解。

我们再来看另外一个例子:

在这个例子中,有两个坐标,这两个坐标其实也是可以相加的,相加之后你二舅会形成一个新的坐标。可是,这两个坐标相加对于加号本身来说,并不具备这样的功能。为了能让其具备这样的功能,我们就可以通过运算符重载来实现。同时,如果我们想直接输出一个坐标,我们也可以通过重载输出运算符来实现。

下面我们来看一看运算符重载的本质!

其实,运算符重载的本质就是:函数重载它并没有什么神秘的地方。

下面介绍一下,定义运算符重载的关键字:operator。

那么,运算符重载其实有很多种,包括:一元运算符重载、二元运算符的重载等。

一元运算符重载

对于一元运算符的重载,在这里,我们举两个例子:

-(负号)的重载

++符号的重载

所谓负号,就是将减号(-)写在某个对象的前面,把它当作一元运算符(所谓一元运算符,就是这个符号只与一个操作数进行运算,比如说:加号其实就是一个二元运算符,因为加号需要由两个操作数来进行运算,而正号,即就是将加号放在一个操作数的前面,那么它就是一个一元运算符),使这个对象进行取反运算。

++符号也是一个一元运算符,可是++符号的运算可以放在操作数的前面,也可以放在操作数的后面。

负号的重载方式:一种是友元函数重载,一种是成员函数重载。友元函数重载,换句话说,就是在类当中去定义一个友元函数,这个友元函数是一个全局函数,用这个友元函数来做运算符的重载,从而实现一个符号多了一项功能。成员函数的重载,其实就是在定义一个类的成员函数。

负号(-)成员函数重载

我们来看这个例子,在这个例子当中,我们定义了一个Coordinate坐标类。如果我们想要对负号(-)做成员函数的重载,我们就应该写成Coordinate& operator-(),因为是一元运算符,而且它是作为类的成员函数存在,所以这里不需要传入任何的参数。实现的时候怎么来做呢?如下

请大家注意,其实我们不传入参数作为一个普通的成员函数来说,它还是有一个隐性的this指针的,而这个隐性的this指针其实就是它的操作数,那么我们就可以将每一个数据成员取反后,再重新复制给它,使得它的所有的数据成都由正变成了负,或者是都由负变成了正,然后将(*this)作为返回值返回出去即可。我们再来看一看如何使用,如下:

需要在对象的前面写一个负号(-),就会使得当前的这个Coordinate对象所有的值都会取反,就相当于使用Coordinate这个对象coor1去调用operator-()这个函数,也就是说这两者是等价的。当计算机遇到这样的时候,就会将其解释成一个函数的调用。

负号(-)友元函数重载

下面我们再来看一下友元函数重载是怎样实现负号运算符重载的。

我们来看这个例子,还是Coordinate这个坐标类,但是这个时候,我们使用友元申明:通过friend关键字来申明一个全局函数operator-,那么这个时候我们需要传入一个参数,这个参数就是Coordinate的一个引用,其返回值也是一个Coordiante的引用。实现的时候我们需要通过这个引用变量分别对它的每一个数据成员取反,然后再赋值给其本身,最后将(*this)返回回去,如下:

调用的时候,当我们给对象coor1取反的时候,计算机就会将其解释成operator-(),并且传入对象coor1,即:operator-(coor1),如下:

请大家比对成员函数重载和友元函数重载的区别。对于成员函数重载,调用的时候是coor1.operator-(),而对于友元函数重载,这里写的是operator-(coor1),这是有本质区别的。

接下来我们说一说++符号的重载,其分为前置++符号重载和后置++符号重载。所谓前置++符号重载,就是将++写在操作数的前面,这一点在C语言当中都已经学习过

++运算符前置重载

我们通过例子来说明这个问题。如果想要做++运算符的前置重载,并且把它当作成员函数来操作的话,我们可以这样来写:

这里注意:因为++是一个一元运算符,所以operator++()中也不用传入任何参数。

那么,定义的时候,我们作为一个成员函数来进行定义,使它的每一个数据成员都做++操作,最后将(*this)返回出去,如下:

这里可以想见一下,外面接收到的值其实就是++之后的值了。如果我们++coor1,就相当于coor1.operator++()的操作,即:


二元运算符重载

加号(+)成员函数重载

我们来看下面的这个例子

在这个类当中,我们除了声明了Coordinate的构造函数之外,还声明了Coordinate operator+();从声明形式来看,它是一个成员函数。这里需要注意的是:在这个成员函数中需要传入一个参数(const Coordinate &coor),我们如何来定义operator+这个函数呢?

我们看到,定义的时候首先需要定义一个临时的Coordinate对象temp,然后传入的这个coor对象的横坐标要与当前对象的横坐标相加,然后将相加之后的值赋值给这个临时对象temp的横坐标(纵坐标处理与横坐标一样),最后将这个临时对象temp作为返回值返回出去。那么,在使用的时候,我们就可以这样来写:

首先,我们定义一个coor1坐标对象,它传入的是3和5,即coor1的横坐标是3,纵坐标是5,同理,coor2的横坐标是4,纵坐标是7,然后我们再定义一个结果,这个结果是coor3对象,用coor3来接收coor1与coor2相加的和。请大家注意:这个对方的加号(+)就已经用到了运算符重载,其就相当于coo1.operator+(coor2)这里需要注意的是:其实作为函数重载来说,加号(+)作为二元运算符在它传入的另外一个参数的前面其实是有一个隐形参数this的,那这个this就相当于传入的第一个参数coor1


#ifndef COORDINATE_H
#define COORDINATE_H

class Coordinate
{
public:
    Coordinate(int x ,int y);
    Coordinate& operator-();//减号运算符重载
    Coordinate& operator+();//加号运算符重载
    Coordinate operator +(const Coordinate &coor);//二元运算符重载
    void  showxy();
    friend void printxy(Coordinate &c);//友元全局函数

private:
    int m_ix;
    int m_iy;
};

#endif // COORDINATE_H

#include <iostream>
#include "coordinate.h"
using namespace std;
//运算符重载实现

Coordinate::Coordinate(int x,int y)
{
  m_ix = x;
  m_iy = y;
}

void Coordinate::showxy()
{
 cout<<"m_ix=="<<m_ix<<" m_iy=="<<m_iy<<endl;

}


Coordinate& Coordinate::operator -(){
    m_ix = -m_ix;
    m_iy = -m_iy;

    return *this;
}


Coordinate& Coordinate::operator +(){
    m_ix ++;
    m_iy ++;

    return *this;
}

Coordinate Coordinate::operator +(const Coordinate &coor){
    Coordinate tmp(0,0);

    tmp.m_ix = this->m_ix + coor.m_ix;//当前对象成员+入参对象成员
    tmp.m_iy = this->m_iy + coor.m_iy;//当前对象成员+入参对象成员

    return tmp;//返回实例对象
}

#include <iostream>
#include "coordinate.h"
#include "time.h"
#include "match.h"

using namespace std;

void printxy(Coordinate &c)//友元全局函数
{
 cout<<"friend m_ix=="<<c.m_ix<<" m_iy=="<<c.m_iy<<endl;

}

int main()
{

    string str1("James");
    string str2("yuan");

    string str3 = str1 + " " + str2;//string对象加号
    cout<<str3<<endl;


    Coordinate coorl(3,5);
    printxy(coorl);//友元全局函数
	
    -(-coorl);//减号运算符重载
    coorl.showxy();

    +coorl;//加号运算符重载
    coorl.showxy();

    Coordinate coorx(1,3);
    Coordinate coory(0,0);

    coory = coorl + coorx;//coorl.operator+(coorx)

    cout<<"#############"<<endl;
    coory.showxy();

    return 0;
}



猜你喜欢

转载自blog.csdn.net/yuanchunsi/article/details/79287385