В каких выражениях присутствует указатель ооп

Обновлено: 22.12.2024

Один из частых вопросов, которые новички задают по поводу классов: «При вызове метода класса, как C++ отслеживает то, какой объект его вызвал?». Ответ заключается в том, что C++ для этих целей использует скрытый указатель *this!

Оглавление:

Скрытый указатель *this

Ниже приведен простой класс, который содержит целочисленное значение и имеет конструктор и функции доступа. Обратите внимание, деструктор здесь не нужен, так как язык C++ может очистить память после переменной-члена самостоятельно:

class Another private : int m_number ; public : Another ( int number ) setNumber ( number ) ; void setNumber ( int number ) < m_number = number ; > int getNumber ( ) < return m_number ; > int main ( ) Another another ( 3 ) ; another . setNumber ( 4 ) ; std :: cout << another . getNumber ( ) << '\n' ; return 0 ;

Результат выполнения программы:

При вызове another.setNumber(4); C++ понимает, что функция setNumber() работает с объектом another , а m_number — это фактически another.m_number . Рассмотрим детально, как это всё работает.

Возьмем, к примеру, следующую строку:

another . setNumber ( 4 ) ;

Хотя на первый взгляд кажется, что у нас здесь только один аргумент, но на самом деле у нас их два! Во время компиляции строка another.setNumber(4); конвертируется компилятором в следующее:

setNumber ( &another , 4 ) ; // объект another конвертировался из объекта, который находился перед точкой, в аргумент функции!

Теперь это всего лишь стандартный вызов функции, а объект another (который ранее был отдельным объектом и находился перед точкой) теперь передается по адресу в качестве аргумента функции.

Но это только половина дела. Поскольку в вызове функции теперь есть два аргумента, то и метод нужно изменить соответствующим образом (чтобы он принимал два аргумента). Следовательно, следующий метод:

void setNumber ( int number ) < m_number = number ; >

Конвертируется компилятором в:

void setNumber ( Another * const this , int number ) < this -> m_number = number ; >

При компиляции обычного метода, компилятор неявно добавляет к нему параметр *this. Указатель *this — это скрытый константный указатель, содержащий адрес объекта, который вызывает метод класса.

Есть еще одна деталь. Внутри метода также необходимо обновить все члены класса (функции и переменные), чтобы они ссылались на объект, который вызывает этот метод. Это легко сделать, добавив префикс this-> к каждому из них. Таким образом, в теле функции setNumber(), m_number (переменная-член класса) будет конвертирована в this->m_number . И когда *this указывает на адрес another , то this->m_number будет указывать на another.m_number .

Соединяем всё вместе:

При вызове another.setNumber(4) компилятор фактически вызывает setNumber(&another, 4) .

Внутри setNumber() указатель *this содержит адрес объекта another .

К любым переменным-членам внутри setNumber() добавляется префикс this-> . Поэтому, когда мы говорим m_number = number , компилятор фактически выполняет this->m_number = number , который, в этом случае, обновляет another.m_number на number .

Хорошей новостью является то, что это всё происходит скрыто от нас (программистов), и не имеет значения, помните ли вы, как это работает или нет. Всё, что вам нужно запомнить — все обычные методы класса имеют указатель *this, который указывает на объект, связанный с вызовом метода класса.

Указатель *this всегда указывает на текущий объект

Начинающие программисты иногда путают, сколько указателей *this существует. Каждый метод имеет в качестве параметра указатель *this, который указывает на адрес объекта, с которым в данный момент выполняется операция, например:

Читайте также: