Почему невозможно преобразовать const X в X &?

Я пытаюсь понять и добиться корректности в проекте Tetris.

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

У меня есть класс (Piece), и один из его закрытых членов класса

Point rotationCenter;

И я пытаюсь написать getter вот так:

inline Point & Piece::getRotationCenter() const
{
  return rotationCenter;
}

Раньше у меня был тот же getter, но не как функция const, и он работал. Теперь я получил ошибку C2240 "невозможно преобразовать const Point to Point &".

Что мне делать, чтобы исправить это? Должен ли я оставить getRotationCenter без const?

PS: Я читаю https://isocpp.org/wiki/faq/const-correctness как учебник.

Ответы

Ответ 1

Почему невозможно преобразовать const X в X &?

Потому что, если это разрешено, становится допустимым следующий опасный код:

const int x = 0;
int& rx = x;     // bind const variable to reference (to non-const)
rx = 99;         // oops, try to modify the const variable via the reference

Что мне делать, чтобы исправить это? Должен ли я оставить getRotationCenter без const?

Это зависит от ваших намерений. Если возвращаемый объект может быть изменен, сделайте функцию-член не константой и верните Point&. Если нет, то оставьте функцию-член const и введите тип возврата const Point&. Функция-член-константа означает обещание, которое не будет изменять (или предоставлять возможность изменения) объекта (и его членов).

Ответ 2

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

Если вы не хотите, чтобы ваш вызывающий абонент модифицировал rotationCenter, вы можете вернуться на Point или const Point&.

inline const Point & Piece::getRotationCenter() const
{
  return rotationCenter;
}

Если вы хотите, чтобы вызывающий абонент модифицировал rotationCenter (который я бы вообще не рекомендовал), напишите две перегрузки: одну, которая возвращает Point&, а другая, которая возвращает const Point& в зависимости от квалификации объекта, который вы назовите его:

inline Point & Piece::getRotationCenter() //not const
{
  return rotationCenter;
}

inline const Point & Piece::getRotationCenter() const
{
  return rotationCenter;
}