2016-11-24 4 views
0

私はオペレータのオーバーロードを練習するために "Safe Array"クラスを実装しようとしています。正しいオブジェクト参照を返すために '[]'演算子をうまくオーバーロードしました。"SafeArray" Pointer's

私の安全な配列の要件の1つは、項目へのポインタがポインタの算術をサポートするということです。例えば、arr[i]へのポインタを指定すると、にアクセスできます。*(&(arr[i]) + 1)でアクセスできます。安全な配列はこの操作も同様に保護しなければならず、範囲外のオブジェクトにアクセスしようとすると例外がスローされます。

この目標を達成する最良の方法は何ですか?

+1

あなたはあなたの「安全なイテレータ」クラスの一部としてこれを実装する必要があります。 –

+2

'operator []'は、 'operator&'をオーバーロードできるクラス型のオブジェクトを返す必要があります。 –

+1

@thecohenoam:あなたは、生の配列とポインタに使用するのと同じ演算子を使うつもりです。変換演算子を使用して、必要な値に変換することができます。それは完璧ではありませんが、主に動作します。 –

答えて

1

template<typename T> 
class SafeArray 
{ 
private: 
    T* m_arr; 
    size_t m_size; 

    T& at(size_t index); 
    const T& at(size_t index) const; 

public: 
    ... 

    class Proxy 
    { 
    private: 
     SafeArray<T>& m_sa; 
     size_t m_index; 

     Proxy(SafeArray<T>& sa, size_t index); 

     friend class SafeArray<T>; 

    public: 
     operator T() const; 
     Proxy& operator=(const T &value); 

     class Ptr 
     { 
     private: 
      SafeArray<T>& m_sa; 
      size_t m_index; 

      Ptr(SafeArray<T>& sa, size_t index); 

      friend class SafeArray<T>::Proxy; 

     public: 
      Ptr operator+(size_t rhs); 
      Ptr operator-(size_t rhs); 
      Ptr& operator++(); 
      Ptr operator++(int); 
      Ptr& operator--(); 
      Ptr operator--(int); 

      Proxy operator*(); 
     }; 

     Ptr operator&(); 
    }; 

    friend class Proxy; 

    Proxy operator[](size_t index); 
}; 

template<typename T> 
T& SafeArray<T>::at(size_t index) 
{ 
    if (index >= m_size) 
     throw std::out_of_range(); 
    return m_arr[index]; 
} 

template<typename T> 
const T& SafeArray<T>::at(size_t index) const 
{ 
    if (index >= m_size) 
     throw std::out_of_range(); 
    return m_arr[index]; 
} 

template<typename T> 
SafeArray<T>::Proxy SafeArray<T>::operator[](size_t index) 
{ 
    return Proxy(*this, index); 
} 

template<typename T> 
SafeArray<T>::Proxy::Proxy(SafeArray<T>& sa, size_t index) 
    : m_sa(sa), m_index(index) 
{ 
} 

template<typename T> 
SafeArray<T>::Proxy::operator T() const 
{ 
    return m_sa.at(m_index); 
} 

template<typename T> 
SafeArray<T>::Proxy& SafeArray <T>::Proxy::operator=(const T &value) 
{ 
    m_sa.at(m_index) = value; 
    return *this; 
} 

template<typename T> 
SafeArray<T>::Proxy::Ptr SafeArray<T>::Proxy::operator&() 
{ 
    return Ptr(m_sa, m_index); 
} 

template<typename T> 
SafeArray<T>::Proxy::Ptr::Ptr(SafeArray<T>& sa, size_t index) 
    : m_sa(sa), m_index(index) 
{ 
} 

template<typename T> 
SafeArray<T>::Proxy::Ptr SafeArray<T>::Proxy::Ptr::operator+(size_t rhs) 
{ 
    return Ptr(m_sa, m_index + rhs); 
} 

template<typename T> 
SafeArray<T>::Proxy::Ptr SafeArray<T>::Proxy::Ptr::operator-(size_t rhs) 
{ 
    return Ptr(m_sa, m_index - rhs); 
} 

template<typename T> 
SafeArray<T>::Proxy::Ptr& SafeArray<T>::Proxy::Ptr::operator++() 
{ 
    ++m_index; 
    return *this; 
} 

template<typename T> 
SafeArray<T>::Proxy::Ptr SafeArray<T>::Proxy::Ptr::operator++(int) 
{ 
    retrurn Ptr(m_sa, m_index++); 
} 

template<typename T> 
SafeArray<T>::Proxy::Ptr& SafeArray<T>::Proxy::Ptr::operator--() 
{ 
    --m_index; 
    return *this; 
} 

template<typename T> 
SafeArray<T>::Proxy::Ptr SafeArray<T>::Proxy::Ptr::operator--(int) 
{ 
    return Ptr(m_sa, m_index--); 
} 

template<typename T> 
SafeArray<T>::Proxy SafeArray<T>::Proxy::Ptr::operator*() 
{ 
    return m_sa[m_index]; 
} 
0

クラスのイテレーターを作成する必要があります。デフォルトでは& arr [i] + 1が安全であることを保証していないはずです(値を返す代わりに、何らかの種類の値を保持する特別なクラスを返さなければならないでしょう)ポインタアクセスのためのオーバーロード、その後のオーバーロード)。

STLが安全を処理する方法は、arr.at(i)などのメンバを使用してイテレータを取得することです。これはデータ型のポインタを保持するクラスですが、イテレータの操作においてある程度の安全性を保証します。

class Array 
{ 
    struct Iterator 
    { 
     Iterator(Array* array, TYPE* ptr) : m_ptr(ptr) {} 
     ... 
     Iterator operator +(int i){ 
      if((m_ptr + i) < m_arr->end()) 
       return Iterator(m_arr, m_ptr + i); 
     } 
    }; 
    ... 
    Iterator at(unsigned int i) { 
     if(i < m_size) 
      return Iterator(this, m_array + i); 
    } 
} 

イテレータには、元の配列クラスへのポインタがあることに注意してください。これは、あなたが尋ねたようにイテレータが境界から外れないようにするために必要ですが、STLイテレータはこのように動作しません。代わりに、iterator < array.end()をチェックして、イテレータがクリエイターについて知る必要がないようにします。何を求めていることなど、少しトリッキーが、いくつかのプロキシオブジェクトを実装することでなんとかです

関連する問題