zoukankan      html  css  js  c++  java
  • 一元运算符重载

    -------------------siwuxie095

       

       

       

       

       

       

       

       

    在 C++ 中,运算符重载既是重点,也是难点

       

    那么,什么是运算符重载呢?

       

    所谓 运算符重载,就是给原有运算符赋予新的功能

       

       

       

       

    如:原来的加号 + 是用来做数字相加操作的,但我们往往

    会用加号 + 去做两个字符串的拼接,其实这就是给加号 +

    做了运算符的重载

       

       

    看如下实例:

       

       

       

    在 main() 函数中就使用了加号 + 去连接多个字符串,使之拼接成

    一个字符串,而且打印时也可以将这个字符串直接打印出来

       

    那么这个字符串就进行了多个运算符的重载,即 加号运算符 + 、

    等号运算符 =、输出运算符 << 都进行了重载

       

       

       

    再看另一个实例:

       

       

       

    在 main() 函数中有两个坐标,它们其实也是可以进行相加的,

    相加之后形成一个新的坐标

       

    但是,坐标相加,对于加号 + 本身来说,并不具备这样的功能,

    为了能够让它具备这样的功能,就可以通过运算符重载来实现

       

    同时,如果想直接输出一个坐标,也可以通过重载输出运算符

    << 来做到

       

       

       

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

       

       

       

       

    定义运算符重载的关键字:operator,即 运算符

       

       

    运算符重载有很多种,包括 一元运算符重载、二元运算符重载

       

       

       

       

       

       

    一元运算符重载

       

       

    所谓 一元运算符,即 这个符号只与一个操作数进行运算

       

       

    1)负号 - 的重载

       

       

       

    负号 - 的重载方式有两种:

       

    第一种是友元函数重载,即 在类中定义一个全局函数作为友元函数,

    用这个友元函数来做运算符的重载,从而实现一个符号多了一项功能

       

    第二种是成员函数重载,其实就是定义一个类的成员函数

       

       

       

    1)先来看成员函数重载,如下:

       

    定义一个坐标类:Coordinate

       

       

       

       

    如果想对负号 - 做成员函数的重载,应该写成这样:Coordinate 接一个

    引用,然后是关键字 operator,后面是负号 -,然后是一对括号

       

    因为是一元运算符,而且是作为类的成员函数存在的,所以不需要在其中

    传任何的参数

       

       

       

    在实现时:

       

       

       

    虽然没有传参数,但作为一个普通的成员函数来说,它还是有一个隐性的

    this 指针的,而这个隐性的 this 指针其实就是它的一个操作数,那么就可

    以将每一个数据成员取反,重新赋值给本身,使得它所有的数据成员都由正

    变为负 都由负变为正,然后将 *this 作为返回值返回出去即可

       

       

       

    在使用时:

       

       

       

    在 main() 函数中先定义一个 Coordinate 的对象 coor1,只需要在

    coor1 的前面取一个负号,就会使得 coor1 的所有值都会取反,就

    相当于是用 coor1 去调用 operator-() 这个函数

       

    -coor1; coor1.operator-(); 是等价的

       

    在计算机解释时,当遇到 -coor1 这样的表示符号,计算机就会把它

    解释为一个函数的调用

       

       

       

    2)再来看友元函数的重载,如下:

       

       

       

    此时,使用友元声明,通过 friend 来声明一个全局函数 operator-()

    并传入参数 Coordinate 的一个引用,它的返回值也是 Coordinate 的

    一个引用

       

       

       

    在实现时:

       

       

       

    通过引用变量分别对它的每一个数据成员取反,并赋值给本身,

    最后将 *this 返回回去

       

       

       

    在使用时:

       

       

       

    当给对象 coor1 取反时,计算机就会把它解释为 operator-(coor1);

       

       

    比对成员函数重载和友元函数重载:

       

    对于成员函数重载,写的是 coor1.operator-();

       

    对于友元函数重载,写的是 operator-(coor1);

       

       

       

       

       

       

    (2)自增符号 ++ 的重载

       

       

       

    自增符号 ++ 的重载方式有两种:一种是 前置++,一种是 后置++

       

       

       

    1)先来看 前置++ 的重载,如下:

       

       

       

    如果想要做 ++ 运算符的前置重载,并把它当做成员函数来操作的话,

    可以这样写:Coordinate& operator++();,因为它是一个一元运算符,

    所以这里也不传入任何参数

       

       

       

    在实现时:

       

       

       

    作为成员函数来进行定义,使它的每一个成员都做 ++ 操作,最后将

    *this 作为返回值返回出去,即 外面接收到的值其实就是 ++ 之后的

    值了

       

       

       

    在使用时:

       

       

       

    如果调用 ++coor1;,就相当于调用 coor1.operator++();, 相当于在

    调一个普通的成员函数

       

    如果传入的是5,在 ++ 之后,就变成了6

       

       

       

    2)再来看 后置++ 的重载,如下:

       

       

       

    计算机要对 后置++ 前置++ 进行区分,所以 后置++ 需要特别注意:

       

    返回值不再是引用,而是 Coordinate 的一个对象,同时,参数一定要传入

    一个 int,这里的 int 是一个标识,它标识当前的 ++ 符号做的是后置重载,

    在使用时,这个 int 并不传入任何值,即便是传入任何值也没有意义,因为

    根本就不去使用它,只是一个标识而已

       

       

       

    在实现时:

       

       

       

    首先要保证有一个旧的值,即 先要定义一个临时对象 old,然后将当前

    的值 *this 先保存到临时对象 old 当中,最后通过 return 将 old 返回出

       

    如果在当前行接收到 后置++ 的值,那么 后置++ 的值也是没有 ++

    之前的值,但是在下一行代码中如果再去使用当前对象时,里面的值

    就已经发生变化了

       

       

       

    在使用时:

       

       

       

    如果调用 coor1++;,就相当于调用 coor1.operator++(0);,即 系统

    会默认为我们传入一个值,一般来说是 0,它没有什么意义,但能够表

    达出这是一个在调用 后置++ 的运算

       

       

       

       

    程序 1

       

    Coordinate.h:

       

    #ifndef COORDINATE_H

    #define COORDINATE_H

       

    #include <iostream>

    using namespace std;

       

       

    class Coordinate

    {

    // 友元函数的负号运算符重载

    //与注释掉的成员函数的负号运算符重载进行对比

    friend Coordinate &operator-(Coordinate &c);

       

    public:

    Coordinate(int x, int y);

    //成员函数的负号运算符重载

    //Coordinate &operator-();

    int getX();

    int getY();

    private:

    int m_iX;

    int m_iY;

    };

       

    #endif

       

       

       

    Coordinate.cpp:

       

    #include "Coordinate.h"

       

    Coordinate::Coordinate(int x, int y)

    {

    m_iX = x;

    m_iY = y;

    }

       

    int Coordinate::getX()

    {

    return m_iX;

    }

       

    int Coordinate::getY()

    {

    return m_iY;

    }

       

    //Coordinate &Coordinate::operator-()

    //{

    // // this->m_iX=-this->m_iX; this->m_iX=-(this->m_iX); 均可注意隐形的this指针

    // m_iX = -m_iX;

    // m_iY = -m_iY;

    // return *this;

    //}

       

       

    //友元全局函数

    Coordinate &operator-(Coordinate &c)

    {

    c.m_iX = -c.m_iX;

    c.m_iY = -c.m_iY;

    return c;

    }

       

       

       

    main.cpp:

       

    #include "stdlib.h"

    #include "Coordinate.h"

       

    int main(void)

    {

    Coordinate coor(3, 5);

    cout << coor.getX() << "," << coor.getY() << endl;

    //成员函数重载

    //-coor;//coor.operator-(); //可以尝试 -(-coor); 负负得正

       

    //友元函数重载

    -coor;// operator-(coor);

    cout << coor.getX() << "," << coor.getY() << endl;

    system("pause");

    return 0;

    }

       

       

       

       

       

       

    程序 2:

       

    Coordinate.h:

       

    #ifndef COORDINATE_H

    #define COORDINATE_H

    #include <iostream>

    using namespace std;

       

       

    class Coordinate

    {

    public:

    Coordinate(int x, int y);

       

    //前置++ 因为是一元运算符在做成员函数重载时就不需要传入参数

    Coordinate &operator++();

       

    //后置++ 有一个参数 int 其实是一个标志型参数

    //告诉编译器当前所做的++运算符重载是后置++的运算符重载

    //

    //编译器看到int就会把它当做后置++的运算符重载标志

    //返回值亦不一样返回的是Coordinate的一个对象而不是一个引用

    Coordinate operator++(int);

    int getX();

    int getY();

    private:

    int m_iX;

    int m_iY;

    };

       

    //因为表达式前置++ 此时表达式的值就是++之后的值

    //把表达式++之后的值当做整个表达式的值就是前置++的实现方式

    //

    //而表达式后置++ 当前的表达式是++之前的那个值而下一行代码

    //再去访问这个对象时才是++之后的这个对象的值所以实现时也要进行特别区分

       

    #endif

       

       

       

    Coordinate.cpp:

       

    #include "Coordinate.h"

       

    Coordinate::Coordinate(int x, int y)

    {

    m_iX = x;

    m_iY = y;

    }

       

    int Coordinate::getX()

    {

    return m_iX;

    }

       

    int Coordinate::getY()

    {

    return m_iY;

    }

       

    //返回出去的值应该是作了++之后的值对每一个数据成员都要做一次++

    Coordinate &Coordinate::operator++()

    {

    m_iX++;// ++m_iX; 均可并不影响函数最终的效果

    m_iY++;//++m_iY;

    return *this;

    }

       

    Coordinate Coordinate::operator++(int)//注意不要漏了int

    {

    //先做一个临时对象temp 或者old 采用直接赋值 *this 放进去

    //用到了拷贝构造函数(因为没有指针并且没有在构造函数中申请内存,

    //所以这里是默认的拷贝构造函数)

    Coordinate old(*this);

    this->m_iX++;

    this->m_iY++;

    //return的是old 这样就能实现当前表达式所拿到的是this ++之前的值

    //而在当前表达式之后再去运行的代码所拿到的对象则是this ++之后的值

    //这样就实现了后置++的效果

    return old;

    }

       

       

       

    main.cpp:

       

    #include "stdlib.h"

    #include "Coordinate.h"

       

    int main(void)

    {

    Coordinate coor(3, 5);

    cout << coor.getX() << "," << coor.getY() << endl;//3,5

    ++coor;

    cout << coor.getX() << "," << coor.getY() << endl;//4,6

    cout << (coor++).getX() << ",";//x=4

    cout << (coor++).getY() << endl;//y=7

    cout << coor.getX() << "," << coor.getY() << endl;//6,8

       

    system("pause");

    return 0;

    }

       

       

       

       

       

       

       

       

       

       

       

    【made by siwuxie095】

  • 相关阅读:
    58. 最后一个单词的长度
    53. 最大子序和
    50. Pow(x, n)
    35. 搜索插入位置
    28. 实现 strStr()
    leetcode 27. 移除元素
    leetcode 26. 删除排序数组中的重复项
    leetcode 21. 合并两个有序链表
    20. 有效的括号
    多线程案例_循环打印_设计4个线程...
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/6815974.html
Copyright © 2011-2022 走看看