Перегрузка C ++ индексный индексный оператор [] таким образом, который позволяет получать ответы на обновления

Рассмотрим задачу написания индексируемого класса, который автоматически синхронизирует его состояние с некоторым внешним хранилищем данных (например, файлом). Чтобы сделать это, класс должен быть осведомлен об изменениях в индексированном значении, которые могут произойти. К сожалению, обычный подход к перегрузке оператора [] не позволяет этого, например ...

Type& operator[](int index)
{
    assert(index >=0 && index < size);
    return state[index];
}

Есть ли способ различить доступ к значению и изменяемое значение?

Type a = myIndexable[2]; //Access
myIndexable[3] = a;  //Modification

Оба эти случая происходят после того, как функция вернулась. Есть ли какой-то другой подход к перегрузке оператора [], который мог бы иметь больше смысла?

25
задан DuncanACoulter 27 August 2010 в 08:21
поделиться

4 ответа

От оператора[] можно узнать только доступ.
Даже если внешний объект использует бесплатную версию, это не означает, что запись будет иметь место, а может быть.

Таким образом, вам нужно вернуть объект, который может обнаруживать изменения.
Лучший способ сделать это — обернуть объект классом, который переопределяет operator=. Затем эта оболочка может сообщить хранилищу, когда объект был обновлен. Вы также можете переопределить Тип оператора (приведение), чтобы можно было получить константную версию объекта для доступа на чтение.

Тогда мы могли бы сделать что-то вроде этого:

class WriteCheck;
class Store
{
  public:
  Type const& operator[](int index) const
  {
    return state[index];
  } 
  WriteCheck operator[](int index);
  void stateUpdate(int index)
  {
        // Called when a particular index has been updated.
  }
  // Stuff
};

class WriteCheck
{ 
    Store&  store;
    Type&   object;
    int     index;

    public: WriteCheck(Store& s, Type& o, int i): store(s), object(o), index(i) {}

    // When assignment is done assign
    // Then inform the store.
    WriteCheck& operator=(Type const& rhs)
    {
        object = rhs;
        store.stateUpdate(index);
    }

    // Still allow the base object to be read
    // From within this wrapper.
    operator Type const&()
    {
        return object;
    }   
};      

WriteCheck Store::operator[](int index)
{   
    return WriteCheck(*this, state[index], index);
}

Более простой вариант:
Вместо того, чтобы предоставлять оператор [], вы предоставляете конкретный метод набора для объекта хранилища и предоставляете доступ для чтения только через оператор []

15
ответ дан 28 November 2019 в 21:29
поделиться

Вы можете сделать так, чтобы (неконстантный) оператор[] возвращал прокси-объект, который хранит ссылку или указатель на контейнер, и в котором оператор = сообщает контейнеру об обновлении.

(Идея использования константного и неконстантного оператора[] является отвлекающим маневром... вы можете знать, что вы только что предоставили неконстантный доступ к объекту, но вы не знаете, будет ли этот доступ все еще используется для чтения или записи, когда эта запись завершается, или иметь какой-либо механизм для обновления контейнера после этого.)

10
ответ дан 28 November 2019 в 21:29
поделиться

Вернуть прокси-объект, который будет иметь:

  • operator=(Type const &) перегружен для записи
  • operator Type() для чтения
4
ответ дан 28 November 2019 в 21:29
поделиться

в приведенном вами примере доступа вы можете получить различие, используя версию const:

const Type& operator [] ( int index ) const;

на боковой заметке, используя size_t в качестве индекса, избавляет от необходимости проверять, если индекс> = 0

1
ответ дан 28 November 2019 в 21:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: