Позволять X
быть классом с функцией-членом f()
,
this
является неявным аргументом для f()
это типа X* const
,
Тогда, если f() const
является константной функцией-членом, тип для this
указатель сейчас const X* const
,
В обоих случаях кажется, что тип для this
указатель const
, Почему тогда это разрешено внутри функции f()
определение для изменения любого члена данных класса X
? Разве мы не должны всегда прибегать к const_cast
как в
void X::f() {
const_cast <int&> (member) = 1;
}
Если f() const
это const, то это способ сделать:
void X::f() const{
const_cast <int&> (member) = 1;
}
(или вы также можете иметь изменяемый член)
Но почему это работает
void X::f() {
member = 1;
}
this
является неявным аргументом дляf()
это типаX* const
,
Не совсем (это на самом деле Rvalue типа X*
), но достаточно близко ради этого вопроса.
В обоих случаях кажется, что тип для этого указателя является const. Почему же тогда внутри определения функции f () разрешено изменять любой элемент данных класса X?
Потому что если указатель является const
(как в X* const
), вы не можете изменить указатель. Вы можете изменить все, на что он указывает. Если это указатель на const (как в const X*
), то вы не можете изменить то, на что оно указывает.
Так что вы никогда не сможете изменить this
сам; ты не можешь писать this = &some_other_object
, В const
функция-член, вы также не можете изменить (не изменяемые) члены *this
без хитроумного const_cast
,
Этот указатель является значением. Ему нельзя присвоить значение, так что этот указатель является постоянным указателем, не имеет значения.
Если f()
является неконстантной функцией-членом, этот указатель указывает на неконстантный X
Таким образом, элемент данных X может быть изменен.
Но если f() const
является функцией-членом const, этот указатель указывает на const const X
поэтому элемент данных X не может быть изменен. Затем необходимо, чтобы элемент данных был изменяемым или const_cast, если кто-то хочет изменить его внутри f() const
определение.
Мы можем сделать, для const_cast,
void X::f() const{
const_cast <int&> (member) = 1;
}
Если member
это ссылка на неконстантный тип int, тогда присваивание принимается компилятором и имеет желаемое поведение. Если member
является ссылкой на const int, поведение не предсказуемо. Сравните это:
const int a = 10;
const int* b = &a;
int* c = const_cast<int*>(b);
// *c = 20;
c — это const_cast для const int *, чье значение a является const. Поведение не определено.
int a1 = 10;
const int* b1 = &a1;
int* c1 = const_cast<int*>(b1);
*c1 = 20;
c1 — это const_cast для const int *, чья точка a является const. Это работает, вы можете свободно присваивать новое значение int, указанному c1.
Известно, что функция-член const не может изменить значение членов-данных. Мы говорим ей, что это потому, что этот указатель pointee является const.