Должна ли константность распространяться на указатели членов?

У меня есть функция-член, которая объявлена ​​const и изменяет данные через указатель. Это кажется вводящим в заблуждение. Должен ли я удалить ключевое слово const?

Я хотел бы знать, как другие справляются с этой ситуацией в своем коде. Люди просто добавляют комментарий, чтобы уточнить, что происходит? Разве они не добавляют ключевое слово const в функцию-член? Может быть, что-то еще полностью?

Любой совет приветствуется.

1

Решение

По сути, у вас есть два варианта:

Глубокая константность:

class Foo
{
T * ptr;
public:
T       & operator*()       { return *ptr; }
T const & operator*() const { return *ptr; }
T       * operator->()       { return ptr; }
T const * operator->() const { return ptr; }
};

Неглубокая константа:

class Foo
{
T * ptr;
public:
T & operator*() const { return *ptr; }
T * operator->() const { return ptr; }
};

Это действительно зависит от вас и от цели вашего класса. Если класс является «умным» указателем, было бы разумно иметь семантику поверхностной константности, поскольку предполагается, что класс должен быть максимально похож на необработанный указатель (и, конечно, вы можете иметь постоянный необработанный указатель на непостоянный указатель) ).

В противном случае вы должны спросить себя, зачем вообще открывать доступ к объекту-указателю на член. Конечно, возможно, что вы захотите предоставить изменчивый доступ через постоянные ссылки на ваш класс, но я думаю, что это особые и редкие обстоятельства. Во-первых, в вашем коде не должно быть столько сырых указателей. Возвращение глубоко константной ссылки путем разыменования указателя должно быть хорошо, но обычно в лучше инкапсулированных функциях «получателя», которые скрывают тот факт, что внутри вашего класса есть указатель, например T const & get() const { return *ptr; },

3

Другие решения

Вообще-то да. Это обманчиво модифицировать что-то, что вы объявляете константой, даже если вы можете это сделать.

Если кто-то использует ваш код и видит const, он ожидает const. Модификация, хотя и разумная для вас, может привести к серьезным проблемам — даже к аварийному завершению программы.

2

Рассмотрим std::vector<Blah> член против Blah* член, используемый для реализации динамического массива. Чаще всего имеет смысл заменить последнее на первое. С Blah* член А const метод может изменять данные в массиве, в то время как с std::vector<Blah> участник const метод не может изменять данные там.

Также рассмотрим матричный класс с методом индексации, который возвращает прокси, который позволяет присваивать элементу. Назначение через прокси изменяет матрицу, а не сам объект прокси. Таким образом, оператор присваивания прокси-объекта может быть (и должен быть) constдля того, чтобы наложить как можно больше ограничений на его эффект, в то время как его основная задача состоит в изменении вещей.

Это еще один пример того, что уровень разработки отличается от уровня кодирования.

В первом примере с массивом членов, const было все о выражении ограничения уровня проекта, но во втором примере, с прокси назначения, const было все о выражении ограничения уровня кодирования.

Однако эти способы использования не являются несовместимыми. Основная идея заключается в том, чтобы предоставить читателю кода как можно больше ограничений (поскольку это значительно уменьшает количество различных вещей, которые необходимо учитывать для понимания или работы с кодом). Апшот: добавить const везде, где вы можете.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector