带下标运算符的重载赋值运算符

Posted

技术标签:

【中文标题】带下标运算符的重载赋值运算符【英文标题】:overloading assignment operator With subscript operator 【发布时间】:2013-12-08 17:32:57 【问题描述】:

我重载了下标运算符和赋值运算符,我试图为赋值运算符获得正确的值 例子 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;

【问题讨论】:

我认为@Dietmar Kühl 的答案是最好的答案。因为它还显示了运算符 int() 的用法,所以cout&lt;&lt;x[0]&lt;&lt;endl; 也可以工作。也许这应该是公认的答案。 【参考方案1】:

它不使用您的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[1]=5 表单中获取正确的值;所以赋值运算符应该返回对象数组 @user2960763 在您添加评论时,我正在添加代理使用示例。【参考方案2】:

如果您在代码中删除 = 运算符的重载,那么您将拥有您想要的行为,因为您的重载 [] 运算符返回对列表项的引用。例如:

#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]$ 和数组长度之外的元素的情况进行错误处理。

【讨论】:

【参考方案3】:

您编写的赋值运算符将应用于数组,而不是数组元素。例如

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

【讨论】:

这应该是公认的答案。它适用于 x[0] 以及 x[1]=5。【参考方案4】:

你想让operator= 做什么?我建议一个更好的签名是

Array& operator=(int x)

它应该 (i) 返回一个自引用 *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)

【讨论】:

我想使用数组的赋值运算符而不是普通的赋值运算符我该怎么做【参考方案5】:

您为Array 类重载了operator=,而不是int(顺便说一句,您不能这样做)。 x[1]=5; 使用Array::operator[] 进行元素访问,它返回int&amp;,然后对=5 部分使用普通的int 赋值运算符。 Array::operator= 仅在您分配给整个对象时使用(即您定义它的方式,您可以使用x = 5;), 分配给它的元素/成员。

【讨论】:

我想用Array类的赋值运算符不正常

以上是关于带下标运算符的重载赋值运算符的主要内容,如果未能解决你的问题,请参考以下文章

重载运算与类型转换——基本概念,输入和输出运算符,算术和关系运算符,赋值运算符,下标运算符,递增和递减运算符,成员访问运算符

C++中赋值运算操作符和=重载有啥区别?

c++中为啥赋值运算符重载返回类型是引用

重载运算符作为成员函数还是非成员函数

C++重载赋值运算符

C++重载赋值运算符