下标运算符的重载有两种形式:
形式1:int& operator [] (int index); // 从外部可更改数组元素
形式2:const int& operator [] (int index) const; // 仅供元素的读写使用
对于形式1来说,其返回值是非const的,所以可以从外部通过下标操作符来更改数组的值,即如下语句是合法的:
Array Arr(10);//定义一个非const对象
arr[5] = 7;//更改有效;相当于arr.operator[](5)=7,调用形式1,因为返回值是非const的,故可以作为左值
int var = arr[3];//访问
对于形式2来说,有两点需要注意:
1)返回值是const的,所以从外部只能通过[]访问数组元素,但不能从外部通过[]来修改数组的值:
const Array brr(6);brr[5] = 7;//非法;相当于brr.operator[](5)=7,调用形式2,因为此时返回值是非const的,故可以作为左值
int var = brr[3];//访问
2)const对象只能调用const成员函数。
这就是明明arr[3]和 brr[3]看起来一样但实质调用的[]重载函数不一样,所以返回值类型也不一样,从而操作结果不一样的原因!!!
扩:非const对象可以调用非const成员函数,也可以调用const成员函数。(所以为什么arr没有调用形式2呢?我也不知道)
换言之:
非const成员函数只能处理非const对象; const成员函数可以处理const对象,也可以处理非const对象。
定义形式1、形式2两种重载函数的好处是,这样可以定义元素写入,读取使用不同的方式。编译器将在读取类对象时调用const函数,而在对类对象执行写入操作时调用非const函数。因此,如果愿意,可在两个下标函数中实现不同的功能。