在 C 编程里操作符重载是一项强大的特性它能够让我们自定义类的行为使其操作更符合直觉和业务需求。其中下标操作符[]的重载尤为重要它使得我们可以像访问数组元素一样访问自定义类对象的元素极大地提升了代码的可读性和可维护性。一、下标操作符重载基础1.1 什么是下标操作符重载下标操作符[]在 C 中常用于访问数组元素。例如对于数组int arr[5]我们可以使用arr[2]来访问数组的第三个元素。当我们定义自定义类时通过重载下标操作符就能让类对象以类似数组的方式进行元素访问。1.2 默认行为与需求对于内置数组下标操作符由语言本身定义。但对于自定义类编译器不会自动提供下标操作符的功能。如果我们希望自定义类对象能够像数组一样使用下标访问元素就需要手动重载下标操作符。1.3 基本语法下标操作符重载函数的基本语法如下代码语言javascriptAI代码解释class ClassName { public: // 重载下标操作符用于非 const 对象 ReturnType operator[](IndexType index) { // 实现元素访问逻辑 return element; } // 重载下标操作符用于 const 对象 const ReturnType operator[](IndexType index) const { // 实现元素访问逻辑 return element; } };ReturnType是返回元素的类型通常为引用类型这样可以支持对元素的读写操作。IndexType是下标的类型一般为整数类型。提供const和非const版本的重载函数是为了保证const对象也能使用下标操作符进行元素访问且不能修改元素。二、下标操作符的核心实现策略2.1 基础实现一维数组模拟代码语言javascriptAI代码解释#include iostream #include stdexcept // for std::out_of_range using namespace std; class IntArray { private: int* data; size_t size; public: IntArray(size_t s) : size(s), data(new int[s]()) {} ~IntArray() { delete[] data; } // 非const下标操作符 int operator[](size_t index) { if (index size) { throw out_of_range(Index out of range); } return data[index]; } // const下标操作符 const int operator[](size_t index) const { if (index size) { throw out_of_range(Index out of range); } return data[index]; } void print() const { for (size_t i 0; i size; i) { cout data[i] ; } cout endl; } }; int main() { IntArray arr(5); for (int i 0; i 5; i) arr[i] i * 10; arr.print(); // 输出: 0 10 20 30 40 try { cout arr[10] endl; // 抛出out_of_range异常 } catch (const out_of_range e) { cerr Error: e.what() endl; } const IntArray c arr; cout c[2] endl; // 输出: 20调用const版本 return 0; }2.2 多维数组实现矩阵类示例代码语言javascriptAI代码解释class Matrix { private: double** data; size_t rows, cols; public: Matrix(size_t r, size_t c) : rows(r), cols(c) { data new double*[r]; for (size_t i 0; i r; i) { data[i] new double[c](); } } ~Matrix() { for (size_t i 0; i rows; i) delete[] data[i]; delete[] data; } // 行代理类实现链式下标操作 class RowProxy { private: double* rowData; public: RowProxy(double* row) : rowData(row) {} double operator[](size_t col) { return rowData[col]; } const double operator[](size_t col) const { return rowData[col]; } }; // 非const下标操作符返回行代理 RowProxy operator[](size_t row) { return RowProxy(data[row]); } // const下标操作符 const RowProxy operator[](size_t row) const { return RowProxy(data[row]); } void print() const { for (size_t i 0; i rows; i) { for (size_t j 0; j cols; j) { cout data[i][j] ; } cout endl; } } }; int main() { Matrix mat(3, 3); mat[0][0] 1.0; mat[0][1] 2.0; mat[0][2] 3.0; mat[1][0] 4.0; mat[1][1] 5.0; mat[1][2] 6.0; mat[2][0] 7.0; mat[2][1] 8.0; mat[2][2] 9.0; mat.print(); /* 输出: 1 2 3 4 5 6 7 8 9 */ mat[1][1] 10.0; // 修改元素 cout mat[1][1] endl; // 输出: 10 const Matrix c mat; cout c[2][2] endl; // 输出: 9调用const版本 return 0; }三、下标操作符的高级用法3.1 自定义索引类型字符串键映射代码语言javascriptAI代码解释#include string #include unordered_map #include iostream using namespace std; class StringMap { private: unordered_mapstring, int data; public: // 自定义索引类型string int operator[](const string key) { return data[key]; // 底层使用std::unordered_map的operator[] } // const版本 const int operator[](const string key) const { auto it data.find(key); if (it data.end()) { throw out_of_range(Key not found); } return it-second; } void print() const { for (const auto pair : data) { cout pair.first : pair.second endl; } } }; int main() { StringMap map; map[apple] 10; map[banana] 20; cout map[apple] endl; // 输出: 10 try { cout map[orange] endl; // 抛出out_of_range } catch (const out_of_range e) { cerr Error: e.what() endl; } const StringMap c map; cout c[banana] endl; // 输出: 20 return 0; }3.2 代理对象实现惰性求值或位级操作示例std::vectorbool的代理模式代码语言javascriptAI代码解释#include vector #include iostream using namespace std; class BitVector { private: vectorunsigned char data; size_t size; class BitProxy { private: BitVector parent; size_t index; public: BitProxy(BitVector p, size_t i) : parent(p), index(i) {} // 转换为bool读取 operator bool() const { size_t byteIndex index / 8; size_t bitIndex index % 8; return (parent.data[byteIndex] (1 bitIndex)) ! 0; } // 赋值操作符写入 BitProxy operator(bool val) { size_t byteIndex index / 8; size_t bitIndex index % 8; if (val) { parent.data[byteIndex] | (1 bitIndex); } else { parent.data[byteIndex] ~(1 bitIndex); } return *this; } }; public: BitVector(size_t s) : size(s), data((s 7) / 8) {} BitProxy operator[](size_t index) { return BitProxy(*this, index); } bool operator[](size_t index) const { size_t byteIndex index / 8; size_t bitIndex index % 8; return (data[byteIndex] (1 bitIndex)) ! 0; } void print() const { for (size_t i 0; i size; i) { cout (*this)[i] ; } cout endl; } }; int main() { BitVector bv(10); bv[0] true; bv[1] false; bv[2] true; bv.print(); // 输出: 1 0 1 0 0 0 0 0 0 0 cout bv[2] endl; // 输出: 1调用const版本 return 0; }四、下标操作符的边界与异常处理4.1 常见错误场景越界访问未检查索引范围导致未定义行为。const对象修改缺少const版本或const版本返回非const引用。链式调用歧义多维数组中未正确设计代理类导致语法错误。