Указатель '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
Использование указателя (вместо передачи структуры напрямую) необходимо для модификации. Если бы вы передали структуру по значению, функция получила бы копию, и любые изменения были бы потеряны после завершения работы функции. Указатель гарантирует, что изменения сохранятся в исходной структуре.
Задание
ЛегкоДавайте создадим модуль 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):
- Инициализируйте
Timerначальным значением секунд - Вызовите
timer_tick, чтобы добавить указанное количество - Выведите текущее количество секунд
- Вызовите
timer_reset, чтобы сбросить таймер - Снова выведите секунды (должно быть 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;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Object Oriented Programming
1Основы модульного программирования
Заголовочные файлыСтражи включенияИсходные файлыСтатические функцииПовторение: Модульный калькулятор4Инкапсуляция
Концепция непрозрачных указателейОпределение непрозрачных структурГеттеры и сеттерыВалидация в сеттерахИтоги: Секретный ящик2Объекты и методы
Структуры как объектыУказатель 'Self'Константная корректностьУказатель против значенияВспомогательные методыИтоги: Point Manager5Проект: Простой банковский счет
Настройка проектаРеализация счета3Жизненный цикл объекта
Паттерн «Конструктор»Паттерн «Деструктор»Инициализация в стекеГлубокое копированиеПовторение: String Wrapper6Наследование через композицию
Встраивание структурПравило первого элементаДоступ к элементам родителяUpcastingПовторение: Иерархия фигур9Проект: Рисование фигур
Обзор проектаРеализация круга