如果对象中有数组,重载下标运算符[],操作对象中的数组将像操作普通数组一样方便。
下标运算符必须以成员函数的形式进行重载。
下标运算符重载函数的语法:
返回值类型 &perator[](参数);
或者:
const 返回值类型 &operator[](参数) const;
使用第一种声明方式,[]不仅可以访问数组元素,还可以修改数组元素。
使用第二种声明方式,[]只能访问而不能修改数组元素。
在实际开发中,我们应该同时提供以上两种形式,这样做是为了适应const对象,因为通过const 对象只能调用const成员函数,如果不提供第二种形式,那么将无法访问const对象的任何数组元素。
在重载函数中,可以对下标做合法性检查,防止数组越界。
下面是一个示例代码,展示如何为一个包含整数数组的简单类IntArray
重载下标运算符[]
。我们将提供两种形式的重载:一种允许修改数组元素,另一种仅允许访问数组元素(适用于常量对象)。这样做可以确保即使是常量对象也能通过下标运算符安全地访问数组元素,同时提供数组越界的检查。
#include <iostream>
#include <stdexcept> // 用于std::out_of_range
class IntArray {
private:
int* array;
size_t size;
public:
// 构造函数
IntArray(size_t size) : size(size), array(new int[size]) {}
// 析构函数
~IntArray() {
delete[] array;
}
// 下标运算符重载(非const版本)
int& operator[](size_t index) {
if (index >= size) {
throw std::out_of_range("Index out of range");
}
return array[index];
}
// 下标运算符重载(const版本)
const int& operator[](size_t index) const {
if (index >= size) {
throw std::out_of_range("Index out of range");
}
return array[index];
}
// 获取数组大小
size_t getSize() const { return size; }
};
int main() {
IntArray arr(10);
for (size_t i = 0; i < arr.getSize(); ++i) {
arr[i] = static_cast<int>(i * 10);
}
try {
for (size_t i = 0; i <= arr.getSize(); ++i) {
std::cout << "Element at index " << i << " is " << arr[i] << std::endl;
}
} catch (const std::out_of_range& e) {
std::cout << "Caught an exception: " << e.what() << std::endl;
}
return 0;
}
代码说明
- 构造函数 和 析构函数:负责管理内部动态数组的内存。
- 非const版本的下标运算符 (
int& operator[](size_t index)
):允许修改数组元素。如果提供的下标超出数组界限,抛出一个std::out_of_range
异常。 - const版本的下标运算符 (
const int& operator[](size_t index) const
):仅允许访问数组元素,用于常量对象。同样,如果下标超界也会抛出异常。
通过同时提供这两种形式的重载,你的类将更加灵活,能够处理常量和非常量的使用场景,同时通过异常处理增加了运行时的安全性。这种方式非常适用于需要封装内部数据结构且要求安全访问的场景。