Вы можете думать, что указатель this
является неявным аргументом для функций.Представьте себе небольшой класс, такой как
class C {
public:
C( int x ) : m_x( x ) { }
void increment( int value ) {
m_x += value; // same as 'this->m_x += value'
}
int multiply( int times ) const {
return m_x * times; // same as 'return this->m_x * times;'
}
private:
int m_x;
};
, который позволяет вам писать код, подобный
C two( 2 );
two.increment( 2 );
int result = two.multiply( 3 );
Теперь, в действительности, происходит то, что функции-члены increment
и multiply
вызываютсядополнительный аргумент-указатель, указывающий на объект, для которого вызывается функция.Этот указатель известен как this
внутри метода.Тип указателя this
отличается в зависимости от того, является ли метод const
(как multiply
) или нет (как в случае с increment
).
Вы можете сделать что-токак и вам самим, подумайте:
class C {
public:
C( int x ) : m_x( x ) { }
void increment( C * const that, int value ) {
that->m_x += value;
}
int multiply( C const * const that, int times ) const {
return that->m_x * times;
}
private:
int m_x;
};
вы можете написать код, подобный
C two( 2 );
two.increment( &two, 2 );
int result = two.multiply( &two, 3 );
Обратите внимание, что тип указателя this
равен C const * const
для multiply
функция, поэтому как сам указатель const
, так и объект, на который указывает!Вот почему вы не можете изменять переменные-члены внутри метода const
- указатель this
имеет тип, который запрещает это.Это может быть решено с помощью ключевого слова mutable
(я не хочу, чтобы зацикливаться слишком далеко, поэтому я не буду объяснять, как это работает), но даже с использованием const_cast
:
int C::multiply( int times ) const {
C * const that = const_cast<C * const>( this );
that->m_x = 0; // evil! Can modify member variable because const'ness was casted away
// ..
}
Я упоминаю об этом, поскольку он демонстрирует, что this
не такой особенный указатель, как может показаться, и этот конкретный взлом часто является лучшим решением, чем создание переменной-члена mutable
, поскольку этот взлом является локальным для одногофункция, тогда как mutable
делает переменную mutable для всех const
методов класса.