Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лекции / Лекции 1-2.docx
Скачиваний:
0
Добавлен:
11.02.2026
Размер:
142.98 Кб
Скачать

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

В большинстве случаев вам не нужно явно указывать указатель this. Тем не менее, иногда это может быть полезным.

Например, если у вас есть конструктор (или метод), который имеет параметр с тем же именем, что и переменная-член, то устранить неоднозначность можно с помощью указателя this:

class Something {

private:

Int data;

public:

Something(int data) {

this->data = data;

}

};

Здесь конструктор принимает параметр с тем же именем, что и переменная-член. В этом случае data относится к параметру, а this->data относится к переменной-члену. Хотя это приемлемая практика, но рекомендуется использовать префикс m_ для всех имен переменных-членов вашего класса, так как это помогает предотвратить дублирование имен в целом!

Цепочки методов класса

Иногда бывает полезно, чтобы метод класса возвращал объект, с которым работает, в виде возвращаемого значения.

Основной смысл здесь — это позволить нескольким методам объединиться в «цепочку», работая при этом с одним объектом!

Мы на самом деле пользуемся этим уже давно.

Например, когда мы выводим несколько данных с помощью std::cout:

std::cout << "Hello, " << userName;

В этом случае std::cout является объектом, а операция << — методом, который работает с этим объектом.

Компилятор обрабатывает фрагмент, приведенный выше, следующим образом:

(std::cout << "Hello, ") << userName;

Сначала операция << использует std::cout и строковый литерал Hello для вывода Hello в консоль.

Однако, поскольку это часть выражения, операция << также должен возвратить значение (или void). Если операция << возвращает void, то получается следующее:

(void) <<…

Что явно не имеет никакого смысла (компилятор выдаст ошибку). Однако, вместо этого, операция << возвращает разыменованный указатель *this, что в этом контексте является просто самим объектом std::cout. Таким образом, после обработки первого оператора <<, мы получаем:

(std::cout) << userName;

Что приводит к выводу имени пользователя (userName).

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

Мы сами можем реализовать такое поведение. Рассмотрим следующий класс:

class Mathem {

private:

int m_value;

public:

Mathem() { m_value = 0; }

void add(int value) { m_value += value; }

void sub(int value) { m_value -= value; }

void multiply(int value) { m_value *= value; }

int getValue() { return m_value; }

};

Если вы хотите добавить 7, вычесть 5 и умножить всё на 3, то нужно сделать следующее:

#include <iostream>

int main() {

Mathem operation;

operation.add(7); // возвращает void

operation.sub(5); // возвращает void

operation.multiply(3); // возвращает void

std::cout << operation.getValue() << '\n';

return 0;

}

Результат:

6

Однако, если каждая функция будет возвращать через указатель this сам объект- *this, то мы сможем связать эти вызовы методов в одну цепочку. Например:

class Mathem {

private:

int m_value;

public:

Mathem() { m_value = 0; }

Mathem& add(int value) { m_value += value; return *this; }

Mathem& sub(int value) { m_value -= value; return *this; }

Mathem& multiply(int value) { m_value *= value; return *this; }

int getValue() { return m_value; }

};

Обратите внимание, add(), sub() и multiply() теперь возвращают сам объект *this, поэтому следующее будет корректным:

#include <iostream>

int main() {

Mathem operation;

operation.add(7).sub(5).multiply(3);

std::cout << operation.getValue() << '\n';

return 0;

}

Результат:

6

Мы фактически вместили три отдельные строки в одно выражение! Теперь рассмотрим это детально:

Сначала вызывается operation.add(7), который добавляет 7 к нашему m_value.

Затем add() возвращает *this, который является ссылкой на объект operation.

Затем вызов operation.sub(5) вычитает 5 из m_value и возвращает operation.

multiply(3) умножает m_value на 3 и возвращает operation, который уже игнорируется.

Однако, поскольку каждая функция модифицировала operation, m_value объекта operation теперь содержит значение ((0 + 7) - 5) * 3), которое равно 6.