Ключевое слово this представляет указатель на текущий объект данного класса. Соответственно через this мы можем обращаться внутри класса к любым его членам.
#include <iostream>
class Point
{
public:
Point(int x, int y)
{
this->x = x;
this->y = y;
}
void showCoords()
{
std::cout << "Point x: " << this->x << "\t y: " << y << std::endl;
}
private:
int x;
int y;
};
int main()
{
Point p1{20, 50};
p1.showCoords();
}
В данном случае определен класс Point, который представляет точку на плоскости. И для хранения координат точки в классе определены переменные x и y.
Для обращения к переменным используется указатель this. Причем после this ставится не точка, а стрелка ->.
В большинстве случаев для обращения к членам класса вряд ли поднадобится ключевое слово this. Но оно может быть необходимо, если параметры функции или переменные, которые определяются внутри функции, называются также как и переменные класса. К примеру, чтобы в конструкторе разграничить параметры и переменные класса как раз и используется указатель this.
Другое практическое применение this - с его помощью можно возвращать текущий объект класса:
#include <iostream>
class Point
{
public:
Point(int x, int y)
{
this->x = x;
this->y = y;
}
void showCoords()
{
std::cout << "Coords x: " << x << "\t y: " << y << std::endl;
}
Point &move(int x, int y)
{
this->x += x;
this->y += y;
return *this;
}
private:
int x;
int y;
};
int main()
{
Point p1{20, 50};
p1.showCoords(); // Point x: 20 y: 50
p1.move(10, 5).move(10, 10);
p1.showCoords(); // Point x: 40 y: 65
}
Здесь метод move с помощью указателя this возвращает ссылку на объект текущего класса, осуществляя условное перемещение точки. Таким образом, мы можем по цепочке для одного и того же объекта вызывать метод move:
p1.move(10, 5).move(10, 10);
Здесь также важно отметить возвращение не просто объекта Point, а ссылки на этот объект. Так, в данном случае выше определенная строка фактически будет аналогично следующему коду:
p1.move(10, 5); p1.move(10, 10);
Но если бы метод move возвращал бы не ссылку, а посто объект:
Point move(int x, int y)
{
this->x += x;
this->y += y;
return *this;
}
То вызов p1.move(10, 5).move(10, 10) был бы фактически эквивалентен следующему коду:
Point temp = p1.move(10, 5); temp.move(10, 10);
Где второй вызов метода move вызывался бы для временной копии и никак бы не затрагивал переменную p1.
В качестве альтернативы можно возвращать сам указатель this:
#include <iostream>
class Point
{
public:
Point(int x, int y)
{
this->x = x;
this->y = y;
}
void showCoords()
{
std::cout << "Point x: " << this->x << "\t y: " << y << std::endl;
}
Point* move(int x, int y)
{
this->x += x;
this->y += y;
return this;
}
private:
int x;
int y;
};
int main()
{
Point p1{20, 50};
p1.showCoords(); // Point x: 20 y: 50
p1.move(10, 5)->move(10, 10)->move(10, 15);
p1.showCoords(); // Point x: 50 y: 80
}
В данном случае, поскольку функция move() возвращает указатель this, то у результата функции мы также можем вызвать функцию move через операцию ->:
p1.move(10, 5)->move(10, 10)->move(10, 15)
Другой пример:
#include <iostream>
class Integer
{
public:
Integer(int number)
{
value=number;
}
Integer& add(const Integer& obj)
{
value += obj.value;
return *this;
}
Integer& subtract(const Integer& obj)
{
value -= obj.value;
return *this;
}
Integer& multiply(const Integer& obj)
{
value *= obj.value;
return *this;
}
void print() const
{
std::cout << "Value: " << value << std::endl;
}
private:
int value;
};
int main()
{
Integer num{10};
num.add(Integer{30}).subtract(Integer{15}).multiply(Integer{2});
num.print(); // Value: 50
}
Здесь класс Integer представляет условно целое число, которое хранится в переменной value. В нем определены функции add() (сложение), subtract() (вычитание), и multiply() (умножение), которые принимают другой объект Integer и выполняеют соответствующую операцию между текущим объектом и аргументом. Причем каждая из этих функций возвращает текущий объект, благодаря чему эти функции можно было выполнить по цепочке:
Integer num{10};
num.add(Integer{30}).subtract(Integer{15}).multiply(Integer{2});