Вызов operator[] через operator[] const

346
02 ноября 2017, 07:21
#include <iostream>
class Integer
{
public:
    const int& operator[](size_t i) const
    {
        std::cout << "const int& Integer::operator[](unsigned int) const"
            << std::endl;
        return p[i];
        // return const_cast<Integer&>(*this)[i];
    }
    int& operator[](size_t i)
    {
        std::cout << "int& Integer::operator[](unsigned int)"
            << std::endl;
        return const_cast<int&>(static_cast<const Integer&>(*this)[i] );
        // return p[i];
    }
private:
    int* p;
};

Почему лучше вызывать константный operator[] из не константного operator[] а не наоборот. Я не вижу разницы между этими двумя способами. Ведь константность снимается для временного объекта и только для того что бы вызвать перегруженную функцию.

Answer 1

С самого начала отмечу, что отбрасывать константность нехорошо. Но дублирование кода - тоже плохо. Поэтому в случае вызова неконстантной функции-члена мы отбрасываем константность, т.к. и ожидается объект неконстантный. А если вызываем константный оператор - то нужно гарантировать, что если в нем вызывается другой оператор то он ничего не поменяет, а если этот оператор неконстантный, значит он может что-то поменять, поэтому и гарантий мы таких дать не можем. Следовательно, так вызывать не стоит, это небезопасно.

Как пишет Скотт Мейерс в своей книге «Эффективное использование C++»:

Решать эту задачу наоборот - путем вызова неконстантной версии из константной - неправильно. Помните, что константная функция-член обещает никогда не изменять логическое состояние объекта, а не­ константная не дает таких гарантий. Если вы вызовете неконстантную функцию из константной, то рискуете получить ситуацию, когда объект, который не дол­жен модифицироваться, будет изменен. Вот почему этого не следует делать: что­бы объект не изменился. Фактически, чтобы получить компилируемый код, вам пришлось бы использовать const_cast для отбрасывания константности *this, а это явный признак неудачного решения. Обратная последовательность вызовов - безопасна. Неконстантная > функция-член может де­лать все, что захочет с объектом, поэтому вызов из > нее константной функции­ члена ничем не грозит. Потому-то мы и применяем > к *this оператор static_cast, отбрасывания константности при этом нет.

READ ALSO
Что я делаю не так? C++ [требует правки]

Что я делаю не так? C++ [требует правки]

Перед тем, как задать switch, я пишу int a, дабы задать switch (a)

219
Задача по e-olymp C++ [требует правки]

Задача по e-olymp C++ [требует правки]

Не могу решить эту задачу (проходит 10 из 12 проверок): Задача №33

240
почему не срабатывает move() для sf::CircleShape

почему не срабатывает move() для sf::CircleShape

Не получается задать движение шаров в функции update():

441
msvc2010: ошибка: C2440: инициализация: невозможно преобразовать

msvc2010: ошибка: C2440: инициализация: невозможно преобразовать

Использую std::multiset Он определен в подключаемых заголовках vs2010 Компилятор (msvc2010) ругается на то, что я неверно инициализирую экземпляр std::multiset::const_iterator,...

333