Статья, кажется, охватывает много базовых вопросов, но у автора все еще остается вопрос о постоянных и неконстантных перегрузках функций, возвращающих указатели. Последняя строка статьи:
Многие, вероятно, ответят: «Это зависит». но я хотел бы спросить: «Это зависит от чего?»
Если быть точным, это зависит от того, является ли состояние объекта-объекта A логически частью состояния this
объекта.
Например, vector<int>::operator[]
возвращает ссылку на int. INT referand является «частью» вектора, хотя на самом деле он не является членом данных. Таким образом, применяется идиома const-overload: измените элемент, и вы изменили вектор.
Для примера, где это не так, рассмотрим shared_ptr
. Он имеет функцию-член T * operator->() const;
, поскольку логично иметь умный указатель const на неконстантный объект . Ссылка не является частью умного указателя: изменение его не приводит к изменению умного указателя. Таким образом, вопрос о том, можете ли вы «переустановить» умный указатель для ссылки на другой объект, не зависит от того, является ли реферат постоянным.
Не думаю, что смогу дать какие-либо полные рекомендации, которые позволят вам решить, является ли пуантист логически частью объекта или нет. Однако, если изменение указателя изменяет возвращаемые значения или другое поведение каких-либо функций-членов this
, и особенно если оно участвует в operator==
, то, скорее всего, оно логически является частью this
объекта.
Я бы ошибся, если предположить, что является частью (и обеспечить перегрузки). Затем, если возникла ситуация, когда компилятор жалуется, что я пытаюсь изменить объект A, возвращенный из объекта const, я бы подумал, действительно ли я должен это делать или нет, и если да, то измените дизайн так, чтобы только указатель на A концептуально является частью состояния объекта, а не самого A. Это, конечно, требует, чтобы изменение A не делало ничего, что нарушало бы ожидаемое поведение this
const объекта.
Если вы публикуете интерфейс, вам, возможно, придется выяснить это заранее, но на практике переход от константных перегрузок к const-function-returning-non-const-pointer вряд ли нарушит клиентский код. В любом случае, к тому времени, когда вы публикуете интерфейс, вы, надеюсь, уже немного его использовали и, вероятно, почувствовали, что на самом деле включает в себя состояние вашего объекта.
Кстати, я также пытаюсь ошибиться из-за того, что не предоставляю средства доступа к указателям / ссылкам, особенно модифицируемые. Это действительно отдельная проблема (Закон Деметры и все такое), но чем больше раз вы можете заменить:
A *getA();
const A *getA() const;
с:
A getA() const; // or const A &getA() const; to avoid a copy
void setA(const A &a);
Чем меньше раз вы будете беспокоиться о проблеме. Конечно, у последнего есть свои ограничения.