C++重载下标操作符

前面已经提到,下标操作符[ ]必须要以类的成员函数的形式进行重载。其在类中的声明格式如下:

返回类型 & operator[] (参数)

const 返回类型 & operator[] (参数)

如果使用第一种声明方式,操作符重载函数不仅可以访问对象,同时还可以修改对象。如果使用第二种声明方式,则操作符重载函数只能访问对象,不能修改对象。

在我们访问数组时,通过下标去访问数组中的元素并不具有检查边界溢出功能,我们可以重载下标操作符使之具有相应的功能。

【例 1】
#include<iostream>
#include<string>
using namespace std;

class Array
{
public:
    Array(){length = 0; num = NULL;};
    Array(int n);
    int & operator[]( int );
    const int & operator[]( int )const;
    int getlength() const {return length;}
private:
    int length;
    int * num;
};

Array::Array(int n)
{
    try
    {
        num = new int[n];
    }
    catch(bad_alloc)
    {
        cerr<<"allocate storage failure!"<<endl;
        throw;
    }
    length = n;
}

int& Array::operator[](int i)
{
    if(i < 0 || i >= length)
        throw string("out of bounds");
    return num[i];
}

const int & Array::operator[](int i) const
{
    if(i < 0 || i >= length)
        throw string("out of bounds");
    return num[i];
}

int main()
{
    Array A(5);
    int i;
    try
    {
        for(i = 0; i < A.getlength(); i++)
            A[i] = i;
        for(i = 0 ;i < 6; i++ )
            cout<< A[i] <<endl;
    }
    catch(string s)
    {
        cerr<< s <<", i = "<< i <<endl;
    }
   
    return 0;
}
本例中定义了一个 Array 类,表示的是一个整形数组,类中重载了下标操作符,使之具备检测下标溢出的功能。在本例中重载下标操作符,我们提供了两个版本的重载下标操作符函数:
int & operator[]( int );
const int & operator[]( int )const;
需要注意的是,第一个下标操作符重载函数最后面不带 const,加上 const 意味着该成员函数是常成员函数,如果第一个函数后面也加上了 const,则两个函数仅有返回值不相同,这个不足以用于区分函数,编译器会提示语法错误。

这两种版本的下标操作符重载函数其实很好理解,一个是可以修改类对象,下面一个则只可以访问对象而不能修改对象。对于上面一种下标操作符重载函数的声明,以下两个语句都是有效的:
arr[5] = 7;
int var = arr[3];
换言之,我们既可以访问类对象,同时又能修改类对象。“arr[5]”其实可以理解为:
arr.operator[](5);
而对于下面一种下标操作符重载函数,我们不能修改对象,也就是说语句arr[5]=7;语句是无效的,但是它依然可以用于访问对象,因此int var=arr[3];语句仍然有效。

我们再来看下标操作符重载函数的定义,在函数体内部,先进行下标越界检测,如果出现越界则抛出异常,否则就返回下标 i 所对应的数据。这两种版本的下标操作符重载函数的函数定义都是如此。

我们来看一下程序输出结果:

0
1
2
3
4
out of bounds, i = 5

在例 1 中,即使我们没有定义 const 版本的,上面的例子也可以正确运行,但是非 const 成员函数不能处理 const 对象,因此通常我们在设计程序时,会同时提供两种版本的操作符重载函数。在例 1 中如果我们增添下面一个 display() 顶层函数,用于打印对象数组中的所有元素。
void display(const Array & A)
{
    for(int i=0; i < A.getlength(); i++)
        cout<< A[i] <<endl;
}
此时如果我们在例 1 中没有定义 const 版本的下标操作符重载函数,则例 1 将会出现语法错误,无法通过编译。