Подтвердить что ты не робот

Оператор [] С++ Get/Set

У меня возникают проблемы с указанием разницы между get и set для оператора []. Мне нужно сказать разницу между этими вызовами функций.

cout << data[5];
data[5] = 1;

Я искал его, и ответы, которые я нашел, все равно не помогли. Люди предлагали сделать подписи для разных методов, добавив const. Я сделал это, и оба они оба назвали один и тот же метод.

Существуют подписи, которые я использовал:

const T& operator[](unsigned int index) const;
T& operator[](unsigned int index);

Что я делаю неправильно?

4b9b3361

Ответ 1

Решение заключается в использовании объекта "прокси", который задерживает действительную операцию:

#include <vector>
#include <iostream>

template<typename T>
struct MyArray {
    std::vector<T> data;
    MyArray(int size) : data(size) {}

    struct Deref {
        MyArray& a;
        int index;
        Deref(MyArray& a, int index) : a(a), index(index) {}

        operator T() {
            std::cout << "reading\n"; return a.data[index];
        }

        T& operator=(const T& other) {
            std::cout << "writing\n"; return a.data[index] = other;
        }
   };

   Deref operator[](int index) {
       return Deref(*this, index);
   }
};

int main(int argc, const char *argv[]) {
    MyArray<int> foo(3);
    foo[1] = 42;
    std::cout << "Value is " << foo[1] << "\n";
    return 0;
}

Простая const -ness не может использоваться, потому что вам может потребоваться прочитать из неконстантного экземпляра, то есть причина, по которой вы должны задержать операцию: присваивание происходит "после" доступа, а компилятор не работает " t скажите, будет ли доступ позже использоваться как цель для назначения или нет.

Идея заключается в том, что при доступе вы просто храните запрошенный индекс и ждете, чтобы узнать, происходит ли операция чтения или записи. Предоставляя оператор неявного преобразования из прокси-сервера в T, вы знаете, когда выполняется операция чтения, предоставляя и присваивая оператор прокси от T, который вы знаете при записи.

Ответ 2

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

Но если объект не является const, тогда можно вызвать обе версии оператора [], но компилятор выберет неконстантную версию. Другими словами, для неконстантного объекта неконстантная версия оператора может действовать как "сеттер" или "геттер". Вот почему одна и та же версия вызывается в обоих случаях в вашем примере, потому что ваш объект data не const.

Вам нужно было бы сделать что-то вроде этого:

const Data& data_cref = data;
cout << data_cref[5];  // calls the const version of operator[]

Data& data_ref = data;
data_ref[5] = 1;       // calls the non-const version of operator[]

Ответ 3

Чтобы быть совместимым с обычным значением индекса, оператор индекса обычно возвращает ссылку на элемент, который извлекается. Вернув ссылку, индекс можно использовать с обеих сторон задания.

Следовательно, обычно также полезно определить как константные, так и неконстовые версии этого оператора. При применении к объекту индекс должен возвращать ссылку на const, чтобы он присваивал возвращаемому объекту.

---- С++ Primer, пятое издание

Ответ 4

const версия вашего operator[] будет вызвана для объекта данных const:

const Data data;
cout << data[5];