c ++ неконст-конст-перегруженный выбор метода - PullRequest
0 голосов
/ 29 апреля 2011

В моем классе есть перегруженные const методы:

class A{
  public:
     typedef int data[10];

           data& operator[](int index);
     const data& operator[](int index) const;
}

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

Ответы [ 6 ]

2 голосов
/ 29 апреля 2011

Да: const_cast<A const&>(anAObj)[5].

1 голос
/ 30 мая 2011

Вам необходимо создать класс Proxy, чтобы заменить возвращаемое значение обоих методов. Затем в классе Proxy вы можете обрабатывать операции чтения и записи соответствующим образом. Вот код, который должен скомпилироваться для демонстрации идеи (работа с массивом целых чисел без знака):

typedef unsigned int UINT;

класс А {

class Proxy {
public:

    Proxy(const UINT &number): _number(number) {}

    const Proxy &operator=(const Proxy &obj) {
        cout << "Writting...\n";
        _number = obj._number;
        return *this;
    }

    operator const UINT &() const {
        cout << "Reading...\n";
        return _number;
    }

private:

    UINT _number;
};

общественность:

A(UINT *array): _array(array) {}

Proxy operator[](int index) {
    return _array[index];
}
const Proxy operator[](int index) const {
    return _array[index];
}

частное:

UINT *_array;

};

int main (int argc, char ** argv) {

UINT myArray[] = {0, 1, 2, 3, 4};

A a(myArray);        // Normal A object

UINT num1 = a[1];    // Reading fine
a[1] = num1;         // Writting fine

const A ca(myArray); // Constant A object

UINT num2 = ca[1];   // Reading fine
ca[1] = num2;        // Writting NOT fine (compilation error)

return 0;

}

1 голос
/ 29 апреля 2011

Почему оператор возвращает data&, а не int&, который ссылается на один элемент?

При этом ваши опции включают:

  • Всегда делать копиюдаже если это окажется ненужным.
  • Используйте оператор для чтения или записи и именованный метод (например, GetRef) для другого.
  • Приведите объект к const в точке использования: static_cast<const A&>(obj)[index].
0 голосов
/ 10 ноября 2014

Если вы осуществляете копирование при записи, вам вообще не следует определять эти операторы подписки. Клиенту, который вызывает const версию метода подписки для объекта x, не разрешается впоследствии использовать эту ссылку для изменения компонента x, но ссылка все равно должна отражать изменения, которые вносят другие клиенты ( этот компонент) x. Но это не произойдет со стратегией копирования при записи, поскольку изменение будет происходить не в той копии, на которую указывают ссылки.

Также два клиента, которые вызывают неконстантный оператор подписки с одним и тем же индексом, должны получать (изменяемые) ссылки на один и тот же data объект; но они этого не сделают, потому что при вызове операторов подписки будут сделаны две отдельные копии.

Вместо этого у вас может быть метод подписки, который возвращает data по значению. Это позволяет избежать иллюзии получения псевдонима для компонента x (который, как я утверждал, должен быть иллюзорным при реализации копирования при записи). Вы также можете предоставить один метод, который изменяет компонент x (вместо разделения этой операции на подписку с последующим назначением полученной ссылки), который либо внутренне делает копию, либо просто изменяет компонент на месте, если эта копия была уже сделана. Это скрыло бы от клиентов использование реализации копирования при записи.

В более общем смысле, раскрытие методов, которые возвращают ссылки на внутренние объекты, независимо от того, const или нет, - это раскрытие деталей реализации того, что такие объекты существуют вообще. Это ограничивает свободу изменения реализации позже, например, для сжатия данных или для их хранения в другом месте, чем в памяти.

0 голосов
/ 29 апреля 2011

реализует функции data& at(size_t i); и const data& cat(size_t);, поэтому вы можете вызывать cat() для неконстантных объектов для обеспечения константности возвращаемых данных.

0 голосов
/ 29 апреля 2011

Нет, если вы не приведете ссылку / указатель на константу.Или создайте постоянную копию.

A a;
const_cast<const A &> (a)[0] /*.foo ()*/;
...