2012-09-04 1 views
2

C++에서 연산자 오버로딩에 대한 질문이 있습니다.연산자 오버로드 : C++

할당을 위해 Java의 ArrayList와 같은 배열을 포함하는 클래스를 작성해야합니다.

내가해야 할 일 중 하나는 배열의 크기를 추적하는 것입니다. Size는 포함 된 요소의 양이며, capacity는 클래스가 배열을 확장해야하기 전에 포함될 수있는 최대량입니다.

클라이언트 코드는 생성자를 호출 할 때 크기를 지정합니다. 그러나 새로운 요소가 추가되면 크기를 변경하는 방법을 찾아야합니다.

선생님은 평등의 다른 측면에서 연산자를 오버로드 할 수 있다고 말했습니다. 이게 진짜인가, 아니면 내가 그녀를 오해 했니? 이것이 작동한다면, 내 문제에 대한 최적의 솔루션이 될 것입니다.

에서 [] 연산자에 대한 나의 현재의 오버로드는 다음과 같습니다

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-9999 사이의 요소를 무언가로 채워야한다고 생각하십니까? – juanchopanza

+0

예, 그게 무슨 뜻인지. 요구되는 것과 현재 벡터 크기 사이의 차이점을 고려해야합니다. – WhozCraig

답변

2

원하는대로하지 않는 간단한 접근 방식은 배열이 const 또는 변경 가능한지 여부에 따라 과부하됩니다. 이 배열 (a 좌변 등) 할당의 왼쪽에 사용되거나 (a r- 수치)를 오른쪽되고 있는지를 구별하지 않고

; 단지 그것이 수정 될 수 있는지 여부에 달려 있습니다.

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

당신은 아마 이것을 friendArrayWrapper의 선언 할 필요가; 그럼 그냥 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)을 정의합니다. 인덱스가 범위를 벗어 났지만 setter가 배열을 확장하면 getter는 예외를 throw합니다. 그런 다음, 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

Mike가 당신을 조금이라도 이겼습니다. P. 우리가이 과제와 관련하여 논의한 것처럼 보이지 않기 때문에이 솔루션을 사용할 수 있는지 확신 할 수 없습니다. 그러나 내 문제를 해결할 다른 방법을 찾을 수 없다면이 점을 명심하십시오. – user1646600

+0

@ user1646600 음, 그것은 꽤 표준적인 해결책입니다. (흥미로운 점은 그가 실제로 ArrayWrapper에서 전용 함수로 수행 할 때 프록시에서 실제로 커지기 때문이다. 나는 그것이 중요한 차이를 만든다고 생각하지 않는다.) –