我正在创建自己的边界检查数组类,但遇到了一个问题,即当使用运算符[]时,它无法调用适当的重载函数。
第一个重载运算符[]
用于获取数组示例的实际值(=content):这样指令num1 = list1[2]
是可能的。
第二个重载运算符[]
用于将给定的右值赋给MyArrayList
。
但在运行main
函数时,无法调用第二个,整个代码如下:
#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[]()?
}
我第一次尝试使用friend
关键字重写第二个重载的operator[]()
,但在第二次猜测中,我认为这不是一个好主意,并且没有办法解决这个问题。
2条答案
按热度按时间ogq8wdun1#
可以调用它,但是你必须告诉编译器你希望你的对象是
const
:但是你的方法会给你带来一些非常愤怒的用户。你打破了用户对你的类的每一个合理的期望。你的赋值操作符不返回赋值对象,它允许从包含的类型赋值(并且不允许赋值实际不同的容器),并且它依赖于内部状态,出于某种原因,通过
operator[]
设置。预期的实现应如下所示:
8yoxcaq72#
这里的基本问题是,您不理解当类
MyArrayList
重载了operator[]()
,并且提供了const
和非const
版本时会发生什么。(在这种情况下,类被模板化的事实并没有改变什么)。**注意:**我并没有提到你的
const
和非const
重载有不同的返回类型(对于MyArrayList<int>
,operator[]()
的const
重载返回int
,而非const
重载返回MyArrayList<int> &
)。简而言之-不要这样做!在调用站点,给定类型为
MyArrayList<int>
的对象list1
和表达式list1[2]
,两个operator[]()
都是被调用的候选对象。当
const
和非const
重载都可用时,调用哪个(粗略地说)取决于对象list1
是否为const
。在你的代码中,
list1
不是const
。这就是为什么main()
可以调用list1.add_element(6)
(以及add_element()
的其他调用)。这也是为什么operator[]()
的非const
重载被调用。在表达式
list1[2] = 5
中,list1[2]
作为一个完整的子表达式进行计算。= 5
与调用operator[]()
的哪个重载无关,当然也不会强制选择operator[]()
(您的const
重载返回int &
)。粗略地说,
operator[]()
的const
版本将被调用的唯一情况是对象是const
或者对象是通过const
引用访问的。例如,如果将以下两行添加到
main()
则
operator()[]
的const
过载将被调用。另一个例子是创建一个函数
这也将调用相同的
const
过载。