Definire struct opache
Fa parte della sezione Programmazione orientata agli oggetti del percorso C di Coddy. Lezione 18 di 61.
Ora che hai compreso il concetto di puntatori opachi, vediamo come completare lo schema. L'intestazione dichiara che esiste un tipo, ma è nel file sorgente che definisci cosa contiene effettivamente.
Ecco la configurazione completa. Per prima cosa, l'header con solo la dichiarazione anticipata:
// counter.h
#ifndef COUNTER_H
#define COUNTER_H
typedef struct Counter Counter; // Tipo incompleto
Counter *create_counter(int start);
void free_counter(Counter *c);
#endif
Quindi, il file sorgente contiene la definizione effettiva della struct:
// counter.c
#include "counter.h"
#include <stdlib.h>
struct Counter {
int value; // Nascosto all'esterno!
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);
}
Il punto chiave: struct Counter { ... } compare solo nel file .c. Qualsiasi file che include counter.h sa che Counter esiste, ma non può vedere value o step. Tentare di scrivere c->value in main.c causerebbe un errore del compilatore: i membri sono davvero invisibili.
Questa separazione è alla base dell'incapsulamento in C. Il passo successivo consiste nel fornire un accesso controllato tramite funzioni getter e setter.
Sfida
FacileCostruiamo un modulo Timer che dimostra il pattern del puntatore opaco. Ti eserciterai a nascondere la definizione della struttura nel file sorgente, rendendo i suoi membri interni completamente invisibili al codice che usa il tuo modulo.
Creerai tre file:
timer.h: questa è la tua interfaccia pubblica. Dichiara un tipo opacoTimerusando solo una dichiarazione anticipata: qui non inserire il corpo della struttura! Dichiara anche due funzioni:create_timer(accetta un intero che rappresenta i secondi e restituisce un puntatore a Timer) efree_timer(accetta un puntatore a Timer ed esegue la pulizia). Usa le include guard con il simboloTIMER_H.timer.c: qui si trova il segreto. Definisci la verastruct Timercon due membri nascosti:int secondseint running(usa 1 per lo stato in esecuzione, 0 per lo stato fermo). Implementa il costruttore per allocare la struttura, inizializzaresecondscon il valore fornito e impostarerunninga 1. Implementa il distruttore per liberare la memoria.main.c: usa il tuo modulo Timer per creare un timer e confermare che sia stato creato correttamente. Poiché i membri della struttura sono nascosti, non puoi accedervi direttamente. È proprio questo il punto! Stampa semplicemente un messaggio di conferma della creazione, poi libera il timer e stampa un messaggio di pulizia.
Riceverai un input: il numero di secondi (un intero) con cui inizializzare il timer.
Nel tuo file principale, crea un timer con il valore dei secondi fornito. Stampa un messaggio di creazione, poi libera il timer e stampa una conferma.
Stampa l'output in questo formato:
Timer created
Timer freedL'intuizione fondamentale è che main.c può lavorare con puntatori a Timer, ma non ha modo di accedere direttamente a seconds o running. Tentare di scrivere t->seconds in main.c causerebbe un errore del compilatore, perché il corpo della struttura è definito solo in timer.c. Questa è vera incapsulazione: i dettagli di implementazione sono completamente nascosti agli utenti del tuo modulo.
Provalo tu
#include <stdio.h>
#include "timer.h"
int main() {
int seconds;
scanf("%d", &seconds);
// TODO: Crea un timer con il valore di seconds fornito
// TODO: Stampa "Timer created"
// TODO: Libera la memoria del timer
// TODO: Stampa "Timer freed"
return 0;
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Basi di programmazione modulare
File di intestazioneGuardie di inclusioneFile sorgenteFunzioni staticheRipasso: calcolatrice modulare4Incapsulamento
Il concetto di puntatori opachiDefinire struct opacheGetter e setterLa convalida nei setterRiepilogo: scatola segreta2Oggetti e metodi
Le struct come oggettiIl puntatore 'Self'Correttezza constPuntatore o valoreMetodi di supportoRiepilogo: gestore di punti5Progetto: Conto bancario semplice
Configurazione del progettoImplementazione del conto8Polimorfismo
Puntatori a funzione nelle structSimulare i metodiIl concetto di interfacciaImplementare le interfacceIterazione polimorficaRiepilogo: Greeter11Pattern di progettazione in C
Pattern SingletonPattern FactoryPattern IteratorRiepilogo: Factory di Logger3Ciclo di vita degli oggetti
Pattern del costruttorePattern del distruttoreInizializzazione sullo stackCopia profondaRiepilogo: wrapper di stringhe6Ereditarietà tramite composizione
Incorporamento delle structLa regola del primo membroAccesso ai membri della classe baseUpcastingRiepilogo: gerarchia di forme9Progetto: Disegnatore di forme
Panoramica del progettoImplementazione del cerchioImplementazione del rettangoloUtilizzo polimorficoContenitore di formeEsercitati da solo: Compilatore C online