操作符重载(二)

1. 数组操作符重载

数组操作符重载

通过重载数组操作符,可以使类的对象支持数组的下标访问

  • 数组操作符只能重载为类的成员函数
  • 重载函数能且仅能使用一个参数,也就是数组下标
  • 可以定义不同参数的多个重载函数

在重载数组操作符时,要记得数组操作符的原生语义——数组访问指针运算
a[n] <--> *(a + n) <--> *(n + a) <--> n[a]

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int a[3];
public:
    int &operator [] (int i)
    {
        return a[i];
    }

    int &operator [] (const string &s)
    {
        if( s == "1st" )
        {
            return a[0];
        }
        else if( s == "2nd" )
        {
            return a[1];
        }
        else if( s == "3rd" )
        {
            return a[2];
        }

        return a[0];
    }
};

int main()
{
    Test t;

    for (int i = 0; i < 3; i++)
    {
        t[i] = i;
    }

    for (int i = 0; i < 3; i++)
    {
        cout << t[i] << endl;
    }

    cout << endl;

    cout << t["3rd"] << endl;
    cout << t["2nd"] << endl;
    cout << t["1st"] << endl;

    return 0;
}

数组类IntArray改进

IntArray.h

class IntArray
{
public:
    int &operator [] (int index); //Add
    IntArray &self();             //Add
};

IntArray.cpp

int &IntArray::operator [] (int index)
{
    return m_pointer[index];
}

IntArray &IntArray::self()
{
    return *this;
}

2. 函数操作符重载(函数对象)

  • 函数操作符只能通过类的成员函数重载
  • 可以定义不同参数的多个重载函数
  • 函数操作符重载的本质是使用具体的类对象取代函数,也就是函数对象,函数对象具备函数调用的行为
  • 函数对象用于在工程中取代函数指针
/*
 * 本示例代码实现以下需求:
 * - 编写一个函数,可以获得斐波那契数列每项的值
 * - 每调用一次返回一个值
 * - 函数可根据需要重复使用
*/

#include <iostream>
#include <string>

using namespace std;

class Fib
{
    int a0;
    int a1;
public:
    Fib()
    {
        a0 = 0;
        a1 = 1;
    }

    Fib(int n)
    {
        a0 = 0;
        a1 = 1;

        for(int i = 2; i <= n; i++)
        {
            int t = a1;

            a1 = a0 + a1;
            a0 = t;
        }
    }

    int operator () ()
    {
        int ret = a1;

        a1 = a0 + a1;
        a0 = ret;

        return ret;
    }
};

int main()
{
    Fib fib;

    for(int i = 0; i < 10; i++)
    {
        cout << fib() << endl;
    }

    cout << endl;

    for(int i = 0; i < 5; i++)
    {
        cout << fib() << endl;
    }

    cout << endl;

    Fib fib2(10);

    for(int i = 0; i < 5; i++)
    {
        cout << fib2() << endl;
    }

    return 0;
}

3. 指针操作符重载与智能指针

指针操作符重载

指针操作符指的是->*

  • 指针操作符只能通过类的成员函数重载
  • 重载函数不能使用参数,也就是说,只能定义一个重载函数

智能指针

  • 利用指针操作符重载,可以实现智能指针
  • 智能指针只能用来指向堆空间中的对象或者变量!!!
  • 智能指针在生命周期结束时会自动释放堆空间
  • 智能指针的意义在于减少开发人员的内存管理工作,最大程度上避免内存问题。
/*
 * 实现智能指针类Pointer,要求如下:
 *  - 一片堆空间最多只能由一个指针标识
 *  - 禁止指针运算和指针比较
*/

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int i;
public:
    Test(int i)
    {
        cout << "Test(int i)" << endl;
        this->i = i;
    }
    int value()
    {
        return i;
    }
    ~Test()
    {
        cout << "~Test()" << endl;
    }
};

class Pointer
{
private:
    Test *mp;
public:
    Pointer(Test *p = NULL)
    {
        mp = p;
    }

    Pointer(const Pointer &obj)
    {
        mp = obj.mp;
        const_cast<Pointer &>(obj).mp = NULL;
    }

    Pointer &operator = (const Pointer &obj)
    {
        if (this != &obj)
        {
            delete mp;
            mp = obj.mp;
            const_cast<Pointer &>(obj).mp = NULL;
        }

        return *this;
    }

    Test *operator -> ()
    {
        return mp;
    }

    Test &operator * ()
    {
        return *mp;
    }

    bool isNull()
    {
        return (mp == NULL);
    }

    ~Pointer()
    {
        delete mp;
    }
};

int main()
{
    Pointer p1 = new Test(0);
    Pointer p2 = p1;

    cout << p1.isNull() << endl;
    cout << p2->value() << endl;

    Pointer p3;
    p3 = p2;

    cout << p2.isNull() << endl;
    cout << p3->value() << endl;

    return 0;
}

4. 前置、后置操作符重载

重载实现

前置、后置操作符指的是++--,我们以++为例进行讲解,--和++是一样的

  • 全局函数成员函数均可进行重载
  • 重载前置++操作符不需要参数
  • 重载后置++操作符需要一个int类型的占位参数
#include <iostream>
#include <string>

using namespace std;

class Test
{
    int mValue;
public:
    Test(int i)
    {
        mValue = i;
    }

    int value()
    {
        return mValue;
    }

    Test &operator ++ ()
    {
        ++mValue;

        return *this;
    }

    Test operator ++ (int)
    {
        Test ret(mValue);

        mValue++;

        return ret;
    }
};

int main()
{
    Test t1(0);
    Test t2(0);

    Test t = t1++;

    cout << t.value() << endl;
    cout << t1.value() << endl;

    t = ++t2;

    cout << t.value() << endl;
    cout << t2.value() << endl;

    return 0;
}

前置、后置重载的区别

  • 对于基础类型的变量,前置++和后置++的效率基本相同,没有什么区别
  • 对于类类型的对象,前置++的效率高于后置++,因为后置++重载会调用构造与析构函数
  • 在工程中尽量使用前置++重载以提高程序效率
posted @ 2019-09-23 23:32  原野追逐  阅读(516)  评论(0编辑  收藏  举报