O Ponteiro 'Self'
Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 7 de 61.
Em linguagens orientadas a objetos como Python ou Java, quando você chama object.method(), a linguagem passa automaticamente o próprio objeto para o método. Em C, devemos fazer isso manualmente passando um ponteiro para a struct como o primeiro argumento.
Este ponteiro é convencionalmente chamado de self (emprestado do Python) ou this (do C++). Ele dá à função acesso aos dados da struct para que ela possa lê-los ou modificá-los:
typedef struct {
int health;
} Player;
void player_take_damage(Player *self, int amount) {
self->health -= amount;
}
O ponteiro self é o que faz a função agir como um método — ele sabe qual jogador modificar. Sem ele, a função não teria como acessar a instância específica da struct. Ao chamar esta função, você passa o endereço da sua struct:
Player hero = {100};
player_take_damage(&hero, 25);
// hero.health agora é 75
Usar um ponteiro (em vez de passar a struct diretamente) é essencial para modificação. Se você passasse a struct por valor, a função receberia uma cópia e quaisquer alterações seriam perdidas quando a função retornasse. O ponteiro garante que as alterações persistam na struct original.
Desafio
FácilVamos construir um módulo Timer que rastreia os segundos decorridos. Você praticará o uso do padrão de ponteiro "self" para modificar o estado interno de uma struct por meio de funções que atuam como métodos.
Você criará três arquivos:
timer.h: Declare uma structTimercom um único membroint seconds. Também declare duas funções:timer_tick(recebe um ponteiro para Timer e adiciona um número especificado de segundos) etimer_reset(recebe um ponteiro para Timer e redefine os segundos para zero). Use include guards com o símboloTIMER_H.timer.c: Implemente ambas as funções. A funçãotimer_tickdeve aceitar umTimer *selfe umint amount, e então adicionar o valor aos segundos do timer. A funçãotimer_resetdeve aceitar umTimer *selfe definir seus segundos como zero.main.c: Crie um Timer, realize operações nele e exiba os resultados.
Você receberá duas entradas inteiras: os segundos iniciais para o seu timer e a quantidade a adicionar via tick.
No seu arquivo principal:
- Inicialize um
Timercom o valor de segundos iniciais - Chame
timer_tickpara adicionar a quantidade especificada - Imprima os segundos atuais
- Chame
timer_resetpara resetar o timer - Imprima os segundos novamente (deve ser 0)
Imprima os resultados neste formato:
After tick: {seconds}
After reset: {seconds}Por exemplo, com um valor inicial de 30 e adicionando 15 segundos, a saída seria:
After tick: 45
After reset: 0Folha de consulta
Em C, funções que operam em structs precisam de acesso explícito à instância da struct por meio de um parâmetro de ponteiro, convencionalmente chamado de self ou this:
typedef struct {
int health;
} Player;
void player_take_damage(Player *self, int amount) {
self->health -= amount;
}
O ponteiro self permite que a função acesse e modifique os dados da struct. Ao chamar tais funções, passe o endereço da sua struct:
Player hero = {100};
player_take_damage(&hero, 25);
// hero.health agora é 75
Usar um ponteiro é essencial para modificação — passar por valor criaria uma cópia, e as alterações seriam perdidas quando a função retornasse. O ponteiro garante que as alterações persistam na struct original.
Experimente você mesmo
#include <stdio.h>
#include "timer.h"
int main() {
int initial_seconds, amount_to_add;
scanf("%d", &initial_seconds);
scanf("%d", &amount_to_add);
// TODO: Criar um Timer e inicializá-lo com initial_seconds
// TODO: Chamar timer_tick para adicionar amount_to_add segundos
// TODO: Imprimir os segundos atuais no formato: "After tick: {seconds}"
// TODO: Chamar timer_reset para resetar o timer
// TODO: Imprimir os segundos novamente no formato: "After reset: {seconds}"
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
1Fundamentos da Programação Modular
Arquivos de CabeçalhoInclude GuardsArquivos-FonteFunções EstáticasRecapitulação: Calculadora Modular4Encapsulamento
Conceito de Ponteiros OpacosDefinindo Structs OpacasGetters e SettersValidação em SettersRecapitulação: Caixa Secreta2Objetos e Métodos
Structs como ObjetosO Ponteiro 'Self'Const CorrectnessPonteiro vs ValorMétodos AuxiliaresRecapitulação: Point Manager5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta3Ciclo de Vida de Objetos
Padrão de ConstrutorPadrão de DestrutorInicialização na StackCópia ProfundaRecapitulação: String Wrapper6Herança via Composição
Incorporação de StructsA Regra do Primeiro MembroAcessando Membros PaiUpcastingRecapitulação: Hierarquia de Formas9Projeto: Desenhador de Formas
Visão Geral do ProjetoImplementação do Círculo