自定义MyArrayList类operator[]重载函数调用异常问题求助
问题:自定义数组类MyArrayList的operator[]重载无法正确调用
我正在实现一个带边界检查的自定义数组类MyArrayList,重载了两个operator[]运算符:
- const版本:用于获取元素值,支持
num1 = list1[2]这类取值操作; - 非const版本:用于为元素赋值,支持
list1[2] = 5这类赋值操作。
但运行main函数时,发现无法正确调用对应的重载函数——比如取值操作没有调用到const版本的operator[]。尝试过用friend关键字改写第二个重载函数,但觉得这不是合适方案,现在找不到解决办法,完整代码如下:
#include <iostream> template <typename Data> class MyArrayList { private : Data* data_storage; int num_of_elements; int array_size; int idx_cursor; public : MyArrayList(int _size); void add_element(Data new_data); void remove_element(); Data operator[](int idx) const; MyArrayList& operator[](int idx); void operator=(Data new_data); ~MyArrayList(); }; template <typename Data> MyArrayList<Data>::MyArrayList(int _size) { array_size = _size; data_storage = new Data[array_size]; num_of_elements = 0; idx_cursor = 0; } template <typename Data> void MyArrayList<Data>::add_element(Data new_data) { if(num_of_elements > array_size) { std::cout << "Unable to store more." << std::endl; return; } data_storage[++num_of_elements - 1] = new_data; } template <typename Data> void MyArrayList<Data>::remove_element() { if(num_of_elements <= 0) { std::cout << "Unable to delete anymore" << std::endl; return; } Data* temp = data_storage; delete[] data_storage; data_storage = new Data[--num_of_elements]; for(int i = 0; i < num_of_elements; i++) data_storage[i] = temp[i]; delete[] temp; } template <typename Data> MyArrayList<Data>::~MyArrayList() { delete[] data_storage; } template <typename Data> Data MyArrayList<Data>::operator[](int idx) const { //var = list1[5]; if(idx < 0) { int new_idx = idx; while(new_idx < 0) { std::cout << "IndexOutofBounds! Enter new index." << std::endl; std::cin >> new_idx; std::cout << std::endl; new_idx--; } idx = new_idx; } return data_storage[idx]; } template <typename Data> MyArrayList<Data>& MyArrayList<Data>::operator[](int idx){ // list1[2] = 5; idx_cursor = idx; return *this; } template <typename Data> void MyArrayList<Data>::operator=(Data new_data){ data_storage[idx_cursor] = new_data; } int main() { int num1; MyArrayList<int> list1(5); list1.add_element(6); list1.add_element(7); list1.add_element(8); list1.add_element(9); list1[2] = 5; //possible //std::cout << num1 << std::endl; //not possible. probably not calling the first overloaded operator[]()? }
问题分析与解决方案
核心问题
你的实现逻辑偏离了operator[]的常规设计:
- 非const版
operator[]返回MyArrayList&,再通过额外重载的operator=完成赋值,这不符合C++中operator[]的预期行为——标准容器的operator[]直接返回元素引用,同时支持取值和赋值。 - 这种设计导致非const对象的取值操作(比如
num1 = list1[2])会优先调用非const版operator[],但该版本返回的是对象引用,无法直接转换为Data类型,进而引发异常。
修正方案
直接调整两个operator[]的返回值,让非const版返回元素引用,同时统一边界检查逻辑:
- 修改operator[]返回类型:
- const版保持返回
Data(或const Data&以避免拷贝,提升效率); - 非const版返回
Data&,直接指向数组元素,天然支持赋值和取值。
- const版保持返回
- 抽离边界检查逻辑:将重复的边界检查写成私有成员函数,避免代码冗余。
- 修复其他潜在问题:比如
add_element中的判断条件错误(应为num_of_elements >= array_size),简化remove_element的实现逻辑。
修改后的完整代码
#include <iostream> template <typename Data> class MyArrayList { private: Data* data_storage; int num_of_elements; int array_size; // 统一边界检查,返回合法索引 int validate_index(int idx) const { if (idx < 0 || idx >= num_of_elements) { int new_idx = idx; while (new_idx < 0 || new_idx >= num_of_elements) { std::cout << "IndexOutofBounds! Enter new index (0~" << num_of_elements-1 << "): " << std::endl; std::cin >> new_idx; } idx = new_idx; } return idx; } public: MyArrayList(int _size); void add_element(Data new_data); void remove_element(); Data operator[](int idx) const; // 取值:num1 = list1[2] Data& operator[](int idx); // 赋值/取值:list1[2] = 5 或 num1 = list1[2] ~MyArrayList(); }; template <typename Data> MyArrayList<Data>::MyArrayList(int _size) { array_size = _size; data_storage = new Data[array_size](); // 初始化元素为默认值 num_of_elements = 0; } template <typename Data> void MyArrayList<Data>::add_element(Data new_data) { if (num_of_elements >= array_size) { // 修正判断条件 std::cout << "Unable to store more." << std::endl; return; } data_storage[num_of_elements++] = new_data; // 简化写法 } template <typename Data> void MyArrayList<Data>::remove_element() { if (num_of_elements <= 0) { std::cout << "Unable to delete anymore" << std::endl; return; } num_of_elements--; // 无需重新分配数组,直接减少元素计数即可 } template <typename Data> MyArrayList<Data>::~MyArrayList() { delete[] data_storage; } template <typename Data> Data MyArrayList<Data>::operator[](int idx) const { idx = validate_index(idx); return data_storage[idx]; } template <typename Data> Data& MyArrayList<Data>::operator[](int idx) { idx = validate_index(idx); return data_storage[idx]; } int main() { int num1; MyArrayList<int> list1(5); list1.add_element(6); list1.add_element(7); list1.add_element(8); list1.add_element(9); list1[2] = 5; // 调用非const版operator[]完成赋值 num1 = list1[2]; // 调用非const版operator[]完成取值 std::cout << num1 << std::endl; // 输出5 // 测试const对象调用const版operator[] const MyArrayList<int> const_list = list1; num1 = const_list[1]; // 调用const版operator[] std::cout << num1 << std::endl; // 输出7 }
关键说明
- 非const对象的取值/赋值操作会优先调用非const版
operator[],符合C++重载决议规则; - const对象只能调用const版
operator[],保证了const对象的只读性; - 抽离的
validate_index函数统一处理边界检查,避免代码冗余; - 简化后的
add_element和remove_element修复了原代码中的逻辑错误,提升了效率。
内容的提问来源于stack exchange,提问作者ragedhumancompiler
相关产品推荐
相关产品推荐

