Я перегружен как оператор подписки и оператор присваивания, и я пытаюсь получить правильное значение для оператора присваивания
пример
Array x;
x[0]=5;
перегружая оператор индекса, я могу получить значение 0, но когда я перегружаю оператор присваивания, он выполняет присваивание, но не использует мою перегруженную функцию, потому что переменная 2 должна иметь значение 5.
class Array
{
public:
int *ptr;
int one,two;
Array(int arr[])
{
ptr=arr;
}
int &operator[](int index)
{
one=index;
return ptr[index];
}
int & operator=(int x){
two=x;
return x;
}
};
int main(void)
{
int y[]={1,2,3,4};
Array x(y);
x[1]=5;
cout<<x[0]<<endl;
}
Он не использует ваш operator=
потому что вы не присваиваете экземпляр Array
назначаешь int
, Это вызвало бы вашего оператора:
Array x;
x = 7;
Если вы хотите перехватить назначения на то, что operator[]
возвращает, вы должны вернуть его прокси-объект и определить оператор присваивания для этого прокси. Пример:
class Array
{
class Proxy
{
Array &a;
int idx;
public:
Proxy(Array &a, int idx) : a(a), idx(idx) {}
int& operator= (int x) { a.two = x; a.ptr[idx] = x; return a.ptr[idx]; }
};
Proxy operator[] (int index) { return Proxy(*this, index); }
};
Написанный вами оператор присваивания будет применяться к массиву, а не к элементу массива. Например
x = 5;
будет использовать ваш оператор присваивания. Судя по всему, вы хотите применить перегруженный оператор присваивания при использовании оператора индекса. Единственный способ заставить что-то подобное работать — использовать прокси-класс:
struct Proxy {
Proxy(Array* array, int* element);
void operator= (int rhs) {
array->two = rhs;
*element = rhs;
}
operator int() const { return *element; }
};
Proxy operator[](int index)
{
one=index;
return Proxy(this, ptr + index);
}
Вы перегружены operator=
для Array
класс, не для int
(что вы не можете сделать, кстати). x[1]=5;
использует Array::operator[]
для доступа к элементу, который возвращает int&
, а затем использует нормальный int
оператор присваивания для =5
часть. Array::operator=
используется только когда вы присваиваете весь объект (то есть, как вы его определили, вы можете сделать x = 5;
), не к его элементам / членам.
Что ты хочешь operator=
сделать? Я хотел бы предложить лучшую подпись
Array& operator=(int x)
и он должен (я) вернуть ссылку на себя *this
и (ii) лучше выполнять повторную инициализацию других значений, т. е. может иметь больше смысла очистить ваш массив или сделать что-то подобное.
#include <iostream>
using namespace std;
class Array
{
public:
int *ptr;
int one,two;
Array(int arr[])
:
one(0), two(0)
{
ptr=arr;
}int &operator[](int index)
{
one=index;
return ptr[index];
}
Array & operator=(int x){
two=x;
return *this;
}
};
std::ostream& operator<<(std::ostream& stream, const Array& array)
{
stream << "( " << array.one << ", " << array.two << ": ";
if (array.ptr)
stream << *(array.ptr);
stream << ")";
return stream;
}
int main(void)
{
int y[]={1,2,3,4};
Array x(y);
cout << "Before assigning one element: " << x << endl;
x[1]=5;
cout << "After assigning one element: " << x << endl;
x = 7;
cout << "After operator=: " << x << endl;
}
Запускаемый исходный код по адресу: http://ideone.com/ejefcr
Вот выход. Формат для печати (one, two, ptr[0])
, Я думаю, вы хотите переменную-член one
быть индексом элемента последнего доступа?
Before assigning one element: ( 0, 0: 1)
After assigning one element: ( 1, 0: 1)
After operator=: ( 1, 7: 1)
Если вы удалите перегрузку =
оператор в вашем коде, то вы уже будете иметь желаемое поведение, так как ваш перегружен []
Оператор возвращает ссылку на элемент списка. Например:
#include <iostream>
using namespace std;
template<typename T>
class Array {
private:
// This method is used to reallocate our array when the number of elements becomes equal to the length of the array.
void _grow() {
length *= 2;
T* temp = new T[length];
// Copy over the array elements
for (int i = 0; i <= current; i++) {
temp[i] = items[i];
}
// Delete the old array
delete [] items;
// Set the array pointer equal to the pointer to our new memory, then annihilate the temp pointer
items = temp;
temp = NULL;
}
public:
unsigned int length, current;
T* items;
// Constructor and destructor
Array() {
current = 0;
length = 128;
items = new T[length];
}
~Array() {
delete [] items;
items = NULL;
}
// Overload the [] operator so we can access array elements using the syntax L[i], as in Python
T& operator[] (unsigned int i) {
return items[i];
}
// Add items to the Array if there is room. If there is no room, grow the array and then add it.
void push(T b) {
if (current + 1 < length) {
items[current] = b;
current += 1;
} else {
_grow();
items[current] = b;
current += 1;
}
}
};
int main() {
Array<int> L;
L[0] = 10;
L[1] = 15;
std::cout << L[0] << endl;
std::cout << L[1] << endl;
return 0;
}
Выход:
jmracek:include jmracek$ g++ Array.cpp -o a
jmracek:include jmracek$ ./a
10
15
Если бы я был осторожен, я бы также включил обработку ошибок для случая, когда я пытаюсь, и $ L [i] $ и элемент за пределами длины массива.