-->

overloading assignment operator With subscript ope

2019-02-19 06:12发布

问题:

I overloaded both subscript operator and assignment operator and I am trying to get right value to assignment operator example Array x; x[0]=5; by overloading subscript operator i can get value 0 but when i overload assignment operator it does the assignment but it doesn't use my overloaded function because vaiable 2 should have value 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;
}

回答1:

It does not use your operator= because you are not assigning to an instance of Array, you're assigning to an int. This would invoke your operator:

Array x;
x = 7;

If you want to intercept assignments to what operator[] returns, you must have it return a proxy object and define the assignment operator for that proxy. Example:

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); }
};


回答2:

The assignment operator you wrote would apply to an array, not an array element. For example

x = 5;

would use your assignment operator. From the looks of it you want to have an overloaed assignment operator applied when using the subscript operator. The only way to get something like this to work is using a proxy class:

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);
}


回答3:

You overloaded operator= for the Array class, not for int (which you can't do, by the way). x[1]=5; is using Array::operator[] for element access, which returns an int&, and then uses the normal int assignment operator for the =5 part. Array::operator= is only used when you're assigning to the whole object (i.e. the way you've defined it, you can do x = 5;), not to its elements/members.



回答4:

What do you want the operator= to do? I would suggest a better signature is

Array& operator=(int x)

and it should (i) return a self-reference *this, and (ii) should do a better job of re-initializing other values, i.e. it might make more sense to clear your array or do something like that.

#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;
}

Runnable source code at: http://ideone.com/ejefcr

Here is the output. Format for the printing is (one, two, ptr[0]). I guess you want the member variable one to be the index of the last-accessed element?

Before assigning one element: ( 0, 0: 1)
After  assigning one element: ( 1, 0: 1)
After  operator=:             ( 1, 7: 1)


回答5:

If you remove the overloading of the = operator in your code, then you'll already have the behaviour you're desiring, since your overloaded [] operator returns a reference to the list item. For example:

#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;
}

Output:

jmracek:include jmracek$ g++ Array.cpp -o a
jmracek:include jmracek$ ./a
10
15

If I were being careful, I would also include error handling for the case where I try and $L[i]$ and element outside of the array length.