Menu
Coddy logo textTech

Définir des structures opaques

Fait partie de la section Programmation Orientée Objet du Journey C de Coddy. Leçon 18 sur 61.

Maintenant que tu comprends le concept des pointeurs opaques, voyons comment compléter le pattern. L’en-tête déclare qu’un type existe, mais le fichier source est l’endroit où tu définis ce qu’il contient réellement.

Voici la configuration complète. D'abord, l'en-tête contenant uniquement la déclaration anticipée :

// counter.h
#ifndef COUNTER_H
#define COUNTER_H

typedef struct Counter Counter;  // Type incomplet

Counter *create_counter(int start);
void free_counter(Counter *c);

#endif

Ensuite, le fichier source contient la définition réelle de la structure :

// counter.c
#include "counter.h"
#include <stdlib.h>

struct Counter {
    int value;      // Caché de l'extérieur !
    int step;
};

Counter *create_counter(int start) {
    Counter *c = malloc(sizeof(Counter));
    c->value = start;
    c->step = 1;
    return c;
}

void free_counter(Counter *c) {
    free(c);
}

Le point essentiel : struct Counter { ... } apparaît uniquement dans le fichier .c. Tout fichier qui inclut counter.h sait que Counter existe, mais ne peut pas voir value ou step. Tenter d’écrire c->value dans main.c provoquerait une erreur du compilateur : les membres sont véritablement invisibles.

Cette séparation constitue le fondement de l’encapsulation en C. L’étape suivante consiste à fournir un accès contrôlé par l’intermédiaire de fonctions getter et setter.

challenge icon

Défi

Facile

Construisons un module Timer qui démontre le modèle du pointeur opaque. Tu vas t’entraîner à dissimuler la définition de la structure dans le fichier source, rendant ses membres internes complètement invisibles pour tout code qui utilise ton module.

Tu vas créer trois fichiers :

  • timer.h : c’est ton interface publique. Déclare un type opaque Timer en utilisant uniquement une déclaration anticipée : aucune définition de structure ici ! Déclare également deux fonctions : create_timer (qui prend un entier représentant un nombre de secondes et renvoie un pointeur vers un Timer) et free_timer (qui prend un pointeur vers un Timer et effectue le nettoyage). Utilise des gardes d’inclusion avec le symbole TIMER_H.
  • timer.c : c’est ici que se trouve le secret. Définis la véritable struct Timer avec deux membres cachés : int seconds et int running (utilise 1 pour « en cours d’exécution » et 0 pour « arrêté »). Implémente ton constructeur pour allouer la structure, initialiser seconds avec la valeur fournie et définir running sur 1. Implémente le destructeur pour libérer la mémoire.
  • main.c : utilise ton module Timer pour créer un minuteur et confirmer qu’il a été créé avec succès. Comme les membres de la structure sont cachés, tu ne peux pas y accéder directement. C’est tout l’intérêt ! Affiche simplement un message confirmant la création, puis libère le minuteur et affiche un message de nettoyage.

Tu recevras une entrée : le nombre de secondes (un entier) avec lequel initialiser le minuteur.

Dans ton fichier principal, crée un minuteur avec la valeur de secondes fournie. Affiche un message de création, puis libère le minuteur et affiche une confirmation.

Affiche la sortie dans ce format :

Timer created
Timer freed

L’idée essentielle ici est que main.c peut travailler avec des pointeurs vers des Timers, mais n’a aucun moyen d’accéder directement à seconds ou à running. Tenter d’écrire t->seconds dans main.c provoquerait une erreur du compilateur, car le corps de la structure n’est défini que dans timer.c. C’est cela, le véritable encapsulage : les détails d’implémentation sont complètement cachés aux utilisateurs de ton module.

Essayez vous-même

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

int main() {
    int seconds;
    scanf("%d", &seconds);
    
    // TODO: Créer un timer avec la valeur de secondes fournie
    
    // TODO: Print "Timer created"
    
    // TODO: Libérer le timer
    
    // TODO: Afficher "Timer freed"
    
    return 0;
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C en ligne