Vladimir Privalov
Vladimir Privalov
0
Обложка: Интересные особенности указателя this 

Интересные особенности указателя this 

При работе с классами в C++ мы иногда встречаемся с ключевым словом this. Его можно встретить в методах экземпляра класса. Это ключевое слово не так часто используют, и о нём можно найти мало информации. Тем не менее у this есть интересные особенности и случаи применения, о которых знают не все разработчики C++. В этой статье я расскажу о некоторых интересных особенностях указателя this.

Определение this

Начнём с определения. this — это указатель на объект, из которого мы вызываем метод. С помощью указателя this и оператора -> можно обратиться к полям класса. Например так:

void getX() { return this->x; }

В большинстве случаев мы можем опустить часть this-> и написать просто x.

Теперь рассмотрим некоторые случаи, в которых может быть полезным использование this.

Различие локальной переменной и поля класса с одинаковым именем

Указатель this может быть полезен в случае, когда локальная переменная в методе имеет то же самое имя, что и поле объекта:

void set(int x) { this->x = x; }

Здесь в методе set мы присваиваем полю класса x значение локальной переменной this. Чтобы различить поле класса x и локальную переменную с тем же именем мы используем запись this->x при обращении к полю класса.

this является const указателем

Указатель this является const указателем, то есть неизменяемым. Проверим это на примере:

class Foo {
private:
    int x;
public:
    Foo(int x = 0) {  this->x = x; }
    void change(Foo *foo) { this = foo; }
    void print() { cout << x << endl; }
};

Здесь в методе change мы пытаемся присвоить указателю this новое значение.

Попробуем вызвать метод change в методе main:

Foo obj (3);
Foo *ptr;
obj.change(ptr);
obj.print();

Если мы запустим код, то получим ошибку компиляции в методе change (lvalue required as left operand of assignment). Компилятор не позволяет нам изменить значение указателя this.

Указатель this доступен только внутри нестатических методов класса

Попробуем добавить такой метод в наш класс:

static void set(int x) { this->x = x; }

Здесь мы добавили для метода setмодификатор static.

Теперь вызовем это:

obj.set(6);

Мы получим ошибку компиляции ‘this’ is unavailable for static member functions.

Это объясняется тем, что указатель this передаётся только в нестатические методы класса как скрытый параметр. В статических методах он недоступен.

this удобно использовать для цепочных вызовов

Мы можем вернуть ссылку на объект, на котором мы вызываем метод класса:

Foo &set(int x) { this->x = x; return *this; }

Здесь метод set возвращает ссылку на объект класса Foo(Foo&).

Такая реализация метода позволяем нам писать код, подобный этому:

obj.set(2).set(8);

Здесь мы вызываем метод set со значением 2, а затем ещё раз со значением 8. Это возможно, поскольку первый вызов метода set возвращает указатель на объект obj. Второй метод вызывается на объекте obj. Можно переписать код так:

obj = obj.set(2);
obj = obj.set(8);

Таким образом, мы познакомились с указателем this и узнали о некоторых интересных особенностях при работе с ним.