Что такое указатель this в C++?

Ответ

this — это ключевое слово в C++, представляющее собой указатель на константу (ClassName* const this) на текущий объект, внутри нестатических методов класса. Его тип — ClassName*. В константных методах его тип — const ClassName*.

Основные цели использования:

  1. Разрешение неоднозначности имен: Когда имя параметра метода совпадает с именем поля класса.

    class Widget {
        int id;
    public:
        void setId(int id) {
            this->id = id; // this->id относится к полю класса, id — к параметру.
        }
    };
  2. Возвращение ссылки на текущий объект из метода (для цепочечных вызовов):

    class Logger {
        Logger& log(const std::string& msg) {
            std::cout << msg;
            return *this; // Разыменовываем указатель, возвращаем ссылку.
        }
    };
    // Использование:
    Logger logger;
    logger.log("Hello ").log("Worldn"); // Цепочка вызовов
  3. Передача текущего объекта в другие функции:

    void externalProcessor(MyClass* obj);
    class MyClass {
        void process() {
            externalProcessor(this); // Передаем указатель на себя.
        }
    };
  4. В лямбда-выражениях внутри класса: Для захвата текущего объекта.

    class Task {
        int data;
        void schedule() {
            // Захватываем указатель 'this' для доступа к полям.
            auto job = [this]() { std::cout << data; };
        }
    };

Важные ограничения:

  • this нельзя изменить (это константный указатель).
  • this недоступен в статических методах класса, так как они не привязаны к конкретному экземпляру.
  • В конструкторах и деструкторах this также корректен и указывает на создаваемый/уничтожаемый объект.

Ответ 18+ 🔞

Давай разберем эту тему, чтобы она не казалась какой-то пиздопроебибной. this — это, по сути, твой личный стукач внутри каждого объекта.

Представь, что у тебя класс Человек, и у него есть метод поесть(Борщ борщ). А внутри класса есть поле вес. Как метод поймёт, вес какого именно человека увеличивать? Вот тут и вылезает this, такой внутренний голос, который орёт: «Э, сабака сука, работаем с тем объектом, у которого меня вызвали!».

Что это такое, если по-простому? Это указатель на тот самый объект, для которого метод вызвали. Тип у него — ИмяКласса*. Внутри константных методов он становится const ИмяКласса*, чтобы ты случайно не взъебал объект, который обещали не трогать.

Зачем он нужен, этот хитрожопый указатель?

  1. Когда имена совпали, и ты нихуя не понимаешь. Допустим, ты передал в метод параметр с таким же именем, как поле класса. Компилятор смотрит на это и думает: «Ну и мудя». Чтобы указать, что к чему, тыкаешь this->.

    class Хомяк {
        int вес; // Поле класса
    public:
        void откормить(int вес) { // Параметр метода
            this->вес += вес; // this->вес — это поле, а второй вес — параметр.
        }
    };

    Без this было бы вес += вес; — и компилятор справедливо спросил бы: «Какого хуя? Ты сам от себя охуел?».

  2. Для крутых цепочек вызовов. Хочешь делать так, чтобы методы можно было вызывать друг за другом, как в красивом API? Возвращай *this (то есть ссылку на сам объект).

    class Настройщик {
        Настройщик& включитьФонарь() {
            // ... код включения ...
            return *this; // Возвращаем сам объект!
        }
        Настройщик& выставитьГромкость(int гром) {
            // ... код ...
            return *this;
        }
    };
    // Использование:
    Настройщик нс;
    нс.включитьФонарь().выставитьГромкость(10); // Цепочка, ёпта!

    Красота, а не жизнь. *this — это разыменованный указатель, получается ссылка на себя.

  3. Чтобы сдать себя в чужие руки. Иногда нужно передать указатель на текущий объект в какую-то внешнюю функцию. Без проблем.

    void глобальнаяФункция(Хомяк* указательНаХомяка);
    class Хомяк {
        void добровольно_сдаться() {
            глобальнаяФункция(this); // Смотрите, я здесь! Берите меня!
        }
    };
  4. В лямбдах внутри класса. Захотел внутри метода сделать лямбду, которая работает с полями объекта? Захватывай [this].

    class СекретнаяЗадача {
        int секретныеДанные;
        void запустить() {
            // Лямбда захватывает this и может трогать секретныеДанные.
            auto шпион = [this]() { std::cout << секретныеДанные; };
        }
    };

А где его НЕ искать? Запомни раз и навсегда:

  • В статических методах. Там this — это хуй с горы. Статический метод не привязан ни к какому объекту, ему не на кого указывать. Доступа ноль, ебать.
  • Его нельзя переназначить. this — это константный указатель. Ты не можешь сделать this = другойУказатель;. Компилятор тебе сразу: «Шёл бы ты на хуй со своими идеями».
  • В конструкторах и деструкторах он работает. Там он честно указывает на объект, который сейчас конструируется или благополучно накрывается медным тазом.

Вот и вся магия. Не такой уж он и страшный, этот this. Главное — понимать, что это просто способ сказать «работай с тем самым объектом, у которого ты есть».

Видео-ответы