аватар question@mail.ru · 01.01.1970 03:00

Смысл this в C++ / self в Python

В чем суть self в ООП языка Python и this в C++ (лучше в примерах)?

аватар answer@mail.ru · 01.01.1970 03:00

Верно подмечено, что эти понятия имеют одну и ту же роль в ООП, объектно-ориентированном программировании: это отсылка объекта к самому себе. Она позволяет:

  1. Обращаться к собственным полям (т.е, переменным) и методам;
  2. Передавать объекту самого себя в другие функции и объекты.

Python и C++ отличаются тем, что первая часть в C++ (ещё в Java, C# и Objective-C) реализована автоматически, нам не обязательно постоянно прописывать self или this. Однако это порождает либо путаницу между переменными объекта и локальными, либо постоянное использование нижнего подчёркивания в названии переменных, что, на мой взгляд, не сильно лучше ссылки на объект. Наоборот, в Питоне (и, например, JavaScript'e) необходимо всегда явно указывать, если обращение идёт к полю текущего объекта.

Рассмотрим оба варианта использования.

1) Для обращения к своим полям

Возьмём класс прямоугольник, у него есть две переменные с длинами сторон: a и b, нам нужен метод для вычисления площади – а для этого нужно обращаться из метода к полям объекта. Код на Python:

class Rect:    def __init__(self, a, b):        # по наличию или отсутствию self различаются        # локальные переменные и поля объекта        self.a = a        self.b = b    # self явно присутствует в аргументах методов    def area(self):        retu self.a * self.b

В языке C++ для этого есть разные способы. Вариант А:

class Rect {    private:        int _a, _b;    public:        Rect(int a, int b) {            // нижнее подчёркивание используется для того, чтобы            // различать аргументы/локальные переменные            // и поля объекта            _a = a;            _b = b;        }        int area() {            // this нет ни в аргументах метода,            // ни в обращении к полям объекта            retu _a * _b;        }}

C++, вариант Б:

class Rect {    private:        int a, b;    public:        Rect(int a, int b) : a(a), b (b) {            // такой способ инициализации полей объекта            // позволяет избегать путаницы с аргументами        }        int area() {            // также, для обращения к собственным переменным            // можно использовать this             retu this->a * this->b;        }}

Лирическое отступление

Обратите внимание на то, что в методах на Питоне self всегда указывается явно, а в C++ this принимает значение автоматически. И хотя конструкция применяется одна и та же object.method(data), а в объявлении методов this не используется, на самом деле ссылка на объект присутствует как скрытый первый аргумент. Можно указать объект и явным образом, вот две эквивалентные строки C++ кода:

my_object.push(3);MyClass::push(&my_object, 3);// надеюсь, Вы понимаете C++ значение символов & и *// если нет, спешите скорее разузнать

Для my_object как экземпляра класса такого вида:

class MyClass {    ...    void push(int number) {        ...    }}

Кстати, подобным образом явно указать объект можно и в Питоне:

# неявная передача объекта в первый аргументmy_object.push(2)# явное указание объекта как аргументаMyClass.push(my_object, 2)

2) Для передачи текущего объекта

Например, у нас есть какой-нибудь объект контроллер или контейнер, и объекты нашего класса должны автоматически туда положиться или удалиться из него. Python:

all = []class MyClass:    def __init__(self):        all.append(self)

C++:

class MyClass {public:    MyClass();}vector<MyClass*> all = new vector<MyClass*>();MyClass::MyClass() {    all.push(this);}

Последние

Похожие