带下标运算符的重载赋值运算符
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<<x[0]<<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&
,然后对=5
部分使用普通的int
赋值运算符。 Array::operator=
仅在您分配给整个对象时使用(即您定义它的方式,您可以使用x = 5;
),不 分配给它的元素/成员。
【讨论】:
我想用Array类的赋值运算符不正常以上是关于带下标运算符的重载赋值运算符的主要内容,如果未能解决你的问题,请参考以下文章
重载运算与类型转换——基本概念,输入和输出运算符,算术和关系运算符,赋值运算符,下标运算符,递增和递减运算符,成员访问运算符