Всегда ли указатель this является константой?

Пусть X будет классом с функцией-членом f().

this — это неявный аргумент для f(), он имеет тип X* const.

Затем, если f() const является константной функцией-членом, тип указателя this теперь будет const X* const.

В обоих случаях кажется, что тип указателя thisconst. Почему же тогда внутри определения функции f() разрешено изменять любой член данных класса X? Разве мы не должны всегда прибегать к const_cast как в

void X::f() {        
       const_cast <int&> (member) = 1;    
} 

Если f() const константа, то можно сделать так:

void X::f() const{        
       const_cast <int&> (member) = 1;    
}

(или вы также можете иметь изменяемый член)

Но почему это работает

void X::f() {  
       member = 1;    
}

person kiriloff    schedule 19.04.2013    source источник
comment
И чтобы все запутать, на заре C++ вы могли модифицировать this; это был механизм размещения объекта в определенной области памяти, теперь замененный размещением new.   -  person Pete Becker    schedule 19.04.2013


Ответы (2)


this является неявным аргументом для f(), имеет тип X* const.

Не совсем (на самом деле это rvalue типа X*), но достаточно близко для этого вопроса.

В обоих случаях кажется, что тип этого указателя — const. Почему же внутри определения функции f() разрешено изменять любой член данных класса X?

Потому что, если указатель равен const (как в X* const), вы не можете изменить указатель. Вы можете изменить все, на что он указывает. Если это указатель на константу (как в const X*), то вы не можете изменить то, на что он указывает.

Таким образом, вы никогда не сможете изменить сам this; вы не можете написать this = &some_other_object. В функции-члене const вы также не можете изменять (неизменяемые) члены *this без хитрого const_cast.

person Mike Seymour    schedule 19.04.2013

Этот указатель является rvalue. Ему нельзя присвоить значение, поэтому то, что этот указатель является константным указателем, не имеет значения.

Если f() не является константной функцией-членом, этот указатель указывает на неконстантную X, поэтому член данных X может быть изменен.

Но если f() const является константной функцией-членом, этот указатель указывает на константу const X, поэтому член данных X не может быть изменен. Затем член данных должен быть изменяемым или константным, если кто-то хочет изменить его внутри определения 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 константного int*, чей указатель a является константным. Поведение неопределенное.

int a1 = 10;
const int* b1 = &a1;
int* c1 = const_cast<int*>(b1);
*c1 = 20;  

c1 является const_cast для const int*, чей указатель a является константой. Это работает, вы можете свободно присваивать новое значение int, на которое указывает c1.

Известно, что константная функция-член не может изменять значение элементов данных. Мы говорим ей, что это потому, что тогда указатель этого указателя является константой.

person Community    schedule 19.04.2013