Перегрузка оператора: переполнение стека

У меня есть вопрос о перегрузке операторов в C ++.

Для назначения я должен написать класс, который включает в себя массив, вроде ArrayList в Java.

Одна из вещей, которые я должен сделать, это отслеживать размер массива. Размер — это количество включенных элементов, тогда как емкость — это максимальное количество, которое МОЖЕТ быть включено до того, как класс расширит массив.

Код клиента определяет размер при вызове конструктора. Однако, когда добавляются новые элементы, мне нужно найти способ изменить размер.

Мой учитель сказал что-то о возможности перегрузить оператор для разных сторон равенства. Это настоящая вещь, или я ее неправильно понял? Если это сработает, это будет оптимальным решением моей проблемы.

Моя текущая перегрузка для оператора []:

int & ArrayWrapper::operator [] (int position){

if(position == _size){
if(_size == _capacity){
changeCapacity(_capacity+10);
}
}
return _array[position];
}

Это прекрасно работает для извлечения, но я бы хотел, чтобы, если кто-то вызывал его с левой стороны от «=», он проверял, нужно ли увеличивать размер или нет.

РЕДАКТИРОВАТЬ: Если это не реально, кто-нибудь может придумать другое решение проблемы? Одно из решений, о котором я подумал, — это чтобы метод getSize () просто проходил весь массив каждый раз, когда он вызывался, но я бы действительно не хотел использовать это решение, потому что оно кажется глупым.

РЕДАКТИРОВАТЬ: Для пояснения, я не спрашиваю, работает ли мое расширение массива. Мне нужно добавить 1 к размеру каждый раз, когда добавляется новый элемент. Например, если клиент создает массив размером 15 и емкостью 25, а затем пытается что-то добавить в массив [15], это ДОЛЖНО увеличить размер до 16. Мне было интересно, существует ли способ сделать это с перегрузкой.

2

Решение

Простой подход, который не совсем делает то, что вы хотите, это перегрузить, является ли массив const или изменчивый.

Это не делает различий между тем, используется ли массив в левой части присваивания (как именующий) или справа (как Rvalue); только о том, разрешено ли его изменять или нет.

// Mutable overload (returns a mutable reference)
int & operator[](size_t position) {
if (position >= _size) {
if (position >= _capatity) {
// increase capacity
}
// increase size
}
return _array[position];
}

// Const overload (returns a value or const reference)
int operator[](size_t position) const {
if (position >= _size) {
throw std::out_of_range("Array position out of range");
}
return _array[position];
}

Если вы действительно хотите сказать, назначены ли вам или нет, вам придется вернуть полномочие для справки. Это перегружает присваивание для записи в массив и предоставляет оператор преобразования для получения значения элемента:

class proxy {
public:
proxy(ArrayWrapper & array, size_t position) :
_array(array), _position(position) {}

operator int() const {
if (_position >= _array._array._size) {
throw std::out_of_range("Array position out of range");
}
return _array._array[_position];
}

proxy & operator=(int value) {
if (_position >= _size) {
if (_position >= _capatity) {
// increase capacity
}
// increase size
}
_array._array[_position] = value;
return *this;
}

private:
ArrayWrapper & _array;
size_t _position;
};

Вы, вероятно, должны объявить это friend из ArrayWrapper; тогда просто верни это из operator[]:

proxy ArrayWrapper::operator[](size_t position) {
return proxy(*this, position);
}
2

Другие решения

Этот подход в порядке. Однако в коде есть ошибка: что произойдет, если кто-то вызовет этот оператор с позицией, равной текущему размеру массива плюс 100?

1

Вопрос в том, действительно ли вы хотите различного поведения в зависимости от
какая сторона = ты. Ваша основная идея будет хорошо работать, но будет
расширить массив независимо от того, на какой стороне вы находитесь, например:

ArrayWrapper a(10);
std::cout << a[20] << std::end;

приведет к расширению массива. В таких случаях большую часть времени
предпочтительное поведение было бы для кода выше, чтобы вызвать исключение,
но для

ArrayWrapper a(10);
a[20] = 3.14159;

работать. Это возможно с помощью прокси: сначала вы определяете double
ArrayWrapper::get( int index ) const
а также void ArrayWrapper::set( int
index, double newValue )
; получатель выдаст исключение, если
index выходит за границы, но установщик расширит массив. Затем,
operator[] возвращает прокси, в соответствии с:

class ArrayWrapper::Proxy
{
ArrayWrapper* myOwner;
int           myIndex;
public:
Proxy( ArrayWrapper& owner, int index )
: myOwner( &owner )
, myIndex( index )
{
}
Proxy const& operator=( double newValue ) const
{
myOwner->set( myIndex, newValue );
}
operator double() const
{
return myOwner->get( myIndex );
}
};

Если вы не знакомы с operator double(), это
перегружен оператор преобразования. Это работает так, что если
operator[] находится на левой стороне задания, это будет на самом деле
прокси, который назначается, и оператор присваивания
прокси переходит к set() функция. В противном случае прокси будет
неявно преобразовать в doubleи это преобразование переходит к
get() функция.

0
По вопросам рекламы [email protected]