Menu
Coddy logo textTech

Указатель 'Self'

Часть раздела Object Oriented Programming путешествия по C на Coddy — урок 7 из 61.

В объектно-ориентированных языках, таких как Python или Java, когда вы вызываете object.method(), язык автоматически передает сам объект в метод. В C мы должны делать это вручную, передавая указатель на структуру в качестве первого аргумента.

Этот указатель традиционно называют self (заимствовано из Python) или this (из C++). Он предоставляет функции доступ к данным структуры, чтобы она могла их читать или изменять:

typedef struct {
    int health;
} Player;

void player_take_damage(Player *self, int amount) {
    self->health -= amount;
}

Указатель self — это то, что заставляет функцию вести себя как метод: он знает, какого игрока нужно изменить. Без него у функции не было бы способа получить доступ к конкретному экземпляру структуры. При вызове этой функции вы передаете адрес вашей структуры:

Player hero = {100};
player_take_damage(&hero, 25);
// hero.health теперь 75

Использование указателя (вместо передачи структуры напрямую) необходимо для модификации. Если бы вы передали структуру по значению, функция получила бы копию, и любые изменения были бы потеряны после завершения работы функции. Указатель гарантирует, что изменения сохранятся в исходной структуре.

challenge icon

Задание

Легко

Давайте создадим модуль Timer, который отслеживает прошедшие секунды. Вы попрактикуетесь в использовании паттерна указателя "self" для изменения внутреннего состояния структуры через функции, которые действуют как методы.

Вы создадите три файла:

  • timer.h: Объявите структуру Timer с единственным полем int seconds. Также объявите две функции: timer_tick (принимает указатель на Timer и добавляет указанное количество секунд) и timer_reset (принимает указатель на Timer и сбрасывает секунды до нуля). Используйте include guards с символом TIMER_H.
  • timer.c: Реализуйте обе функции. Функция timer_tick должна принимать Timer *self и int amount, а затем добавлять это количество к секундам таймера. Функция timer_reset должна принимать Timer *self и устанавливать его секунды в ноль.
  • main.c: Создайте Timer, выполните над ним операции и выведите результаты.

Вы получите два целых числа на вход: начальные секунды для вашего таймера и количество для добавления через tick.

В вашем основном файле (main):

  1. Инициализируйте Timer начальным значением секунд
  2. Вызовите timer_tick, чтобы добавить указанное количество
  3. Выведите текущее количество секунд
  4. Вызовите timer_reset, чтобы сбросить таймер
  5. Снова выведите секунды (должно быть 0)

Выводите результаты в следующем формате:

After tick: {seconds}
After reset: {seconds}

Например, при начальном значении 30 и добавлении 15 секунд, вывод будет следующим:

After tick: 45
After reset: 0

Шпаргалка

В языке C функциям, работающим со структурами, требуется явный доступ к экземпляру структуры через параметр-указатель, который по соглашению называют self или this:

typedef struct {
    int health;
} Player;

void player_take_damage(Player *self, int amount) {
    self->health -= amount;
}

Указатель self позволяет функции получать доступ к данным структуры и изменять их. При вызове таких функций передавайте адрес вашей структуры:

Player hero = {100};
player_take_damage(&hero, 25);
// hero.health now 75

Использование указателя необходимо для модификации — передача по значению создаст копию, и изменения будут потеряны после завершения работы функции. Указатель гарантирует, что изменения сохранятся в исходной структуре.

Попробуйте сами

#include <stdio.h>
#include "timer.h"

int main() {
    int initial_seconds, amount_to_add;
    scanf("%d", &initial_seconds);
    scanf("%d", &amount_to_add);
    
    // TODO: Создать Timer и инициализировать его значением initial_seconds
    
    // TODO: Вызвать timer_tick, чтобы добавить amount_to_add секунд
    
    // TODO: Вывести текущее количество секунд в формате: "After tick: {seconds}"
    
    // TODO: Вызвать timer_reset, чтобы сбросить таймер
    
    // TODO: Снова вывести количество секунд в формате: "After reset: {seconds}"
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Object Oriented Programming