2012-09-04 156 views
2

我有一个关于在C++中运算符重载的问题。运算符重载:C++

对于任务,我必须编写一个包含数组的类,有点像Java中的ArrayList。

我必须做的事情之一是跟踪数组的大小。大小是包含的元素的数量,而容量是在类需要扩展数组之前可以包含的最大数量。

客户端代码指定调用构造函数时的大小。但是,当添加新的元素时,我必须找出一种方法来改变大小。

我的老师说了一些关于能够为平等的不同方面重载操作符的内容。这是真的吗,还是我误解了她?如果这有效,这将是我的问题的最佳解决方案。

我的[]操作符重载电流是:

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

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

这工作正常进行检索,但我想它的话,如果有人从“=的左手边称它为'然后检查是否需要扩大规模。

编辑:如果这不是一个真实的东西,任何人都可以想出不同的解决方案的问题?我想到的一个解决方案是每次调用getSize()方法时都会遍历整个数组,但我真的宁愿不使用该解决方案,因为它看起来很俗气。

编辑:澄清,我不问是否我的数组扩展工作。每次添加新元素时,我都需要添加1。例如,如果客户端创建一个大小为15和容量为25的数组,然后尝试向Array [15]添加一些内容,那么应该将大小增加到16.我想知道是否有一种方法可以用于重载。

+2

这听起来有点奇怪。你的意思是,如果你用大小“10”来构造它,并且有人要求获得“100000”,那么你必须将其扩展到“100001”的大小,并用10到99999之间的元素填充一些东西? – juanchopanza

+0

是的,这就是他的意思。您需要考虑要求的内容与当前矢量大小之间的差异。 – WhozCraig

回答

2

一个简单的方法,并不完全符合你的要求,就是重载数组是否为const或mutable。

这并不是否阵列正在对分配的左手侧(作为左值)中使用或在右侧(作为右值)之间进行区分;只是关于是否允许修改。

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

你可能需要声明这个ArrayWrapperfriend;然后就从operator[]返回此:

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

谢谢你的详细回复。我不确定是否允许我创建另一个班级来解决这个问题,但如果我是这样,我会记住你的答案。 – user1646600

1

这种方法没问题。但是,代码中存在错误:如果有人调用该运算符的位置等于阵列的当前大小加上100,会发生什么情况?

+0

我应该为这种情况写一个例外,但是,我还没有得到它。 当你说我的方法很好时,你是什么意思? – user1646600

+0

他的意思是,我认为,如果'[]'操作符出现在语句的左侧或右侧,则无关紧要。 – mah

+0

哎呀,对不起:误解了你的问题。正如@mah所说,无论阵列所在的任务是哪一边,这都可以工作。 –

0

问题是你是否真的要取决于 你是哪的=的侧面不同的行为。你的基本思路将正常工作,但会 展开数组,无论你就在身边,例如:

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

将导致扩大阵列。在大多数情况下,在这种情况下, 首选的行为将是上面的代码引发异常, 但

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

工作。这可以使用代理:首先,您定义了double ArrayWrapper::get(int index) constvoid ArrayWrapper::set(int index, double newValue);如果 索引超出范围,getter将抛出异常,但setter将扩展该数组。然后, 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

迈克打了你一下:P。我不知道我被允许使用这个解决方案,因为它看起来不像我们讨论过的任何与此作业相关的东西。但是,如果我找不到任何其他方式解决我的问题,那么我会牢记这一点。 – user1646600

+0

@ user1646600那么这是一个相当标准的解决方案。 (有趣的是,他在代理中的实际增长,就像我在'ArrayWrapper'中的专用函数那样做,并不是我认为这会产生显着的差异。) –