Указатель this C++
Вместо того, чтобы сразу давать определение, что же это такое — указатель this , предлагаю рассмотреть вместе с вами два простейших примера. В одном мы просто определим две функции setData() и getData() . Одна будет предлагать пользователю ввести данные, вторая будет выводить их на экран соответственно. И обратимся к ним из главной функции main() . А во втором примере, мы создадим класс class SetGetData , методы которого так же будут вносить данные и выводить их на экран. Забегая наперед, скажу, что основным отличием этих функций и методов станет то, как они принимают параметры (аргументы).
#include using namespace std; void setData(char *s, int &n) //функция для принятия данных < cout > n; > void getData(char s[], int n) //отображение данных < cout int main() < setlocale(LC_ALL, "rus"); char str[128] = ""; //объявляем и инициализируем переменные для очистки от мусора int number = 0; setData(str, number); //вызов функций system("cls"); //очистка экрана перед выводом данных на экран getData(str, number); return 0; >
Этот пример, скорей всего, не вызвал у вас никаких вопросов и трудностей в его понимании, если уж вы дошли до изучения этой темы. Тут мы определили две функции — строки 5 — 16. Функция setData(char *s, int &n) принимает два параметра: указатель на строку и адрес переменной типа int , для того чтобы внести изменения в переменные, которые ей передадутся при вызове. Функция getData(char s[], int n) отобразит строку и число , измененные пользователем. Далее в main- функции мы просто объявляем переменные и передаем их в наши функции при вызове.
Результатом работы будет, к примеру, такое сообщение:
CppStudio.com
cppstudio.com - site N1
Тут вот какое дело, если мы, при определении функций, не укажем, какие параметры им надо принять либо не передадим переменные в качестве параметров, при вызове функций — это будет крах программы. Компилятор такого нам не простит — в ы это понимаете .
Теперь рассмотрим второй пример (Тут вы уже сразу обратите внимание на то, что мы не передаем параметры в методы ни при определении, ни при вызове методов):
#include using namespace std; class SetGetData //определяем класс < char str[128]; int number; public: void setData() //метод класса, который принимает данные < cout > number; > void getData() //метод класса, который выводит данные на экран < cout >; int main() < setlocale(LC_ALL, "rus"); SetGetData object; //создаем объект класса object.setData(); //вносим данные system("cls"); //очистка экрана перед выводом данных на экран object.getData(); //данные отображаем на экране return 0; >
Вы видите, что явно мы ни при определении, ни при вызове методов через объект, не указываем с какими параметрами будут работать методы класса. Все дело в том, что при вызове методов, которые принадлежат классу, им неявно передается тот самый указатель this . Это происходит автоматически и незаметно для нас, так как он является скрытым первым параметром любого метода-элемента класса. Указатель this указывает на адрес созданного объекта класса — в нашем случае он получает адрес объекта object и указывает методу setData() в какие элементы объекта надо внести измененные данные, а методу getData() — элементы какого объекта надо отобразить на экране.
Важно знать, что у нас есть возможность использовать указатель this явно. Так, к примеру, выглядело бы определение метода getData() , если бы мы использовали this явно:
void getData() //метод класса, который выводит данные на экран < cout str number
Такая запись так же «пройдет»:
void getData() < cout
В обоих случаях можно обойтись без этого явного указания, но как это делается лучше знать по той причине, что указатель this все же используется программистами явно , в определенных случаях. Только это уже совсем другая тема. В данной статье мы лишь проходим по основам.
Теперь можно и определение дать! Указатель this — это указатель на адрес объекта класса, при этом он является скрытым первым параметром любого метода класса (кроме статических методов), а типом указателя выступает имя класса. И еще кое-что из теории:
- this является зарезервированным словом С++;
- мы можем использовать this явно в методах-элементах класса;
- а вот явно объявить, инициализировать либо изменить указатель this , возможности нет;
Так, совсем коротко, мы дали вам основную информацию по этой теме. Остались вопросы? Задавайте их в комментариях к статье. Без ответа мы вас не оставим.
К сожалению, для данной темы пока нет подходящих задач. Если у вас есть таковые на примете, отправте их по адресу: admin@cppstudio.com. Мы их опубликуем!
This c что это
Ключевое слово this представляет указатель на текущий объект данного класса. Соответственно через this мы можем обращаться внутри класса к любым его членам.
#include class Point < public: Point(int x, int y) < this->x = x; this->y = y; > void showCoords() < std::cout x private: int x; int y; >; int main() < Point p1; p1.showCoords(); >
В данном случае определен класс Point, который представляет точку на плоскости. И для хранения координат точки в классе определены переменные x и y.
Для обращения к переменным используется указатель this . Причем после this ставится не точка, а стрелка -> .
В большинстве случаев для обращения к членам класса вряд ли поднадобится ключевое слово this. Но оно может быть необходимо, если параметры функции или переменные, которые определяются внутри функции, называются также как и переменные класса. К примеру, чтобы в конструкторе разграничить параметры и переменные класса как раз и используется указатель this.
Другое практическое применение this - с его помощью можно возвращать текущий объект класса:
#include class Point < public: Point(int x, int y) < this->x = x; this->y = y; > void showCoords() < std::cout Point &move(int x, int y) < this->x += x; this->y += y; return *this; > private: int x; int y; >; int main() < Point p1; 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);
Здесь также важно отметить возвращение не просто объекта 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) был бы фактически эквивалентен следующему коду:
Point temp = p1.move(10, 5); temp.move(10, 10);
Где второй вызов метода move вызывался бы для временной копии и никак бы не затрагивал переменную p1.
В качестве альтернативы можно возвращать сам указатель this :
#include class Point < public: Point(int x, int y) < this->x = x; this->y = y; > void showCoords() < std::cout x Point* move(int x, int y) < this->x += x; this->y += y; return this; > private: int x; int y; >; int main() < Point p1; 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 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 private: int value; >; int main() < Integer num; num.add(Integer).subtract(Integer).multiply(Integer); num.print(); // Value: 50 >
Здесь класс Integer представляет условно целое число, которое хранится в переменной value. В нем определены функции add() (сложение), subtract() (вычитание), и multiply() (умножение), которые принимают другой объект Integer и выполняеют соответствующую операцию между текущим объектом и аргументом. Причем каждая из этих функций возвращает текущий объект, благодаря чему эти функции можно было выполнить по цепочке:
Integer num; num.add(Integer).subtract(Integer).multiply(Integer);
Что значит *this в c++? [дубликат]
Я только начал изучать программирование. Мне не совсем понятно, зачем метод move() возвращает *this , если this - это уже ссылка на текущий объект. Я бы возвращал просто this .
Отслеживать
2,279 1 1 золотой знак 6 6 серебряных знаков 27 27 бронзовых знаков
задан 29 мар 2021 в 8:52
Дмитрий Уткин Дмитрий Уткин
47 3 3 бронзовых знака
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
this - не ссылка на текущий объект, а указатель. Поэтому, чтобы получился объект, указатель надо разыменовать - *this .
Отслеживать
5,253 2 2 золотых знака 16 16 серебряных знаков 38 38 бронзовых знаков
ответ дан 29 мар 2021 в 8:54
22.2k 2 2 золотых знака 32 32 серебряных знака 52 52 бронзовых знака
"чтобы получился объект" -> "чтобы получилась ссылка"
29 мар 2021 в 9:15
@Qwertiy, вы считаете, что *this вернет &Point?
29 мар 2021 в 9:48
Да, именно Point& он и вернёт. К тому же, у метода в коде именно такой тип.
29 мар 2021 в 9:56
Вы заблуждаетесь, он вернет lvalue типа Point - stackoverflow.com/questions/48388510/…
29 мар 2021 в 9:59
А чем они отличаются?
29 мар 2021 в 10:02
Можно было возвращать просто this если метод move() возвращал указатель.
Point* move(int x, int y) < this->x += x; this->y += y; return this; >
Но, это не очень удобно, так как, например-
Point obj; obj.move(2,3)->showCoords();
нужно обращаться через стрелочку. А если метод возвращал ссылку можно было б просто через точку-
Point obj; obj.move(2,3).showCoords();
Если тип возврата ссылка - нужно this разыменовывать. Так как это указатель.
Ключевое слово this в C++
Ключевое слово this в языке программирования C++ представляет указатель на текущий объект данного класса. Таким образом, через this мы сможем обратиться внутри класса к любым членам этого класса.
В нашем примере определен класс Point, представляющий точку на плоскости. Для того чтобы хранить координаты этой точки, в классе определены переменные x и y.
Так вот, чтобы обращаться к этим переменным, применяется указатель this. При этом после this надо ставить не точку, а стрелку -> .
Однако в большинстве ситуаций вам вряд ли понадобится ключевое слово this для обращения к членам класса. Зато this может быть необходим в том случае, когда параметры функции либо переменные, определяемые внутри функции, называются точно так же, как и переменные класса. Допустим, this применяют, чтобы разграничить параметры и переменные класса в конструкторе.
Кроме того, используя this, вы сможете возвращать текущий объект класса:
В примере выше метод move возвращает посредством this ссылку на объект текущего класса, выполняя условное перемещение точки. В результате появляется возможность осуществлять вызов метода move по цепочке для одного и того же объекта:
Тут следует отметить, что возвращается не просто объект Point, а ссылка на этот объект. То есть строка, определенная выше, по сути, будет аналогично следующему коду:
Но что было бы, если бы метод move возвращал не ссылку, а просто объект?
В таком случае вызов p1.move(10, 5).move(10) был бы по факту эквивалентен коду ниже:
То есть второй вызов метода move вызывался бы в целях создания временной копии, следовательно, он бы никак не затрагивал переменную p1.