вопрос здесь:
int& f() const {return x;}
Ваша функция отмечена const
, поэтому она может быть вызвана только const
экземплярами. Тем не менее, вы возвращаете ссылку не const
, поэтому, если она действительна, вы можете использовать ее для модификации const
экземпляров. Компилятор не доволен этим. Следовательно, f()
должен возвращать const int&
.
С другой стороны, int& operator[](int) const
скомпилирует, так как вы возвращаете ссылку на данные, на которые указывает указатель y
, но вы не можете изменить сам указатель. Другими словами, на примере const
указатель y
равен const
, то есть int * const y
, но не данные. Поэтому побитовое const
-ness сохраняется, но, конечно, логическое const
-ness нет, однако компилятор только заботится о поразрядном const
-ness.
Чтобы применить логическую const
правильность, один вариант состоит в написании 2 версии вашего operator[]
:
const int& operator[](int i) const {return y[i];}
и
int& operator[](int i) {return y[i];}
Обратите внимание, что вторая версия должна быть отмечена не- const
, иначе вы попытаетесь перегрузить две функции, которые отличаются только их возвращаемым типом. Если вы хотите, чтобы избежать дублирования кода в не- const
версии, вы можете использовать версии const
через const_cast
, как
int& operator[](int i)
{
return const_cast<int&>(const_cast<const A&>(*this)[i]); // use the const version
}
EDIT
Существует предложение ввести const
- распространяющихся обертку для указателей типа элементов данных, propagate_const
, что в действительности будет также сделать данные указывают на const
, см
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4057.pdf
Да, я это понял. Но разве он не должен говорить то же самое о функции перегрузки []? – flaviumanica
@flaviumanica Это не возвращает ссылку на элемент данных. – juanchopanza