Programmazione orientata agli oggetti in ANSI-C. Costruzione statica. Inizializzazione

Le descrizioni di classe sono oggetti la cui vita può durare a lungo. Sono costanti ed esistono praticamente tanto quanto dura l'esecuzione dell'applicazione. Se possibile, tali oggetti sono inizializzati al tempo di compilazione. Tuttativa, abbiamo deciso nel capitolo 6 che l'inizializzazione statica rende le descrizioni di classe difficili da gestire nel tempo: l'ordine dei componenti della struttura deve essere concorde con tutte le inizializzazioni, e l'ereditarietà ci forzerebbe a rilevare dinamicamente quali sono i metodi linkati dinamicamente al di fuori dei loro file d'implementazione.

Per l'inizializzazione iniziale, inizializzeremo solo le descrizioni di classe Object e Class a tempo di compilazione come strutture statiche all'interno del file Object.dc. Tutte le altre descrizioni di classe sono generate dinamicamente e i costruttori della metaclasse che iniziano con Class_ctor() si preoccupano dell'ereditarietà e di effettuare la sovrascrittura dei metodi dinamicamente linkati.

Ooc genera le funzioni di inizializzazione per nascondere i dettagli delle chiamate a new() tramite le quali generare le descrizioni di classe, ma il fatto stesso che debbano essere esplicitamente chiamati nel codice dell'applicazione è una sorgente di errori difficili da diagnosticare. Ad esempio, consideriamo InitPoint() e InitCircle visti nella sezione 6.10.

void initPoint (void) {
if (! PointClass)
PointClass = new(Class, "PointClass",
Class, sizeof(struct PointClass),
ctor, PointClass_ctor,
0);
if (! Point)
Point = new(PointClass, "Point",
Object, sizeof(struct Point),
ctor, Point_ctor,
draw, Point_draw,
0);
}

La funzione è progettata per fare il suo lavoro solo una volta, ossia anche se è chiamata ripetutamente genererà una singola istanza di ogni descrizione di classe.

void initCircle (void) {
if (! Circle)
{ initPoint();
Circle = new(PointClass, "Circle",
Point, sizeof(struct Circle),
ctor, Circle_ctor,
draw, Circle_draw,
0);
}
}

Entrambe le funzioni osservano implicitamente la gerarchia delle classi. InitPoint() si assicura che PointClass esista prima di usarla per la generazione della descrizione Point, la chiamata a InitPoint() in InitCircle() garantisce che la descrizione della superclasse Point e la sua descrizione di metaclasse PointClass esistono prima che venga generata la descrizione Circle. Non vi è pericolo di ricorsione: InitCircle() chiama InitPoint() perchè Point è la superclasse di Circle ma InitPoint() non si riferisce a InitCircle() perchè ooc non permette cicli nella relazione di superclasse.

Le cose vanno decisamente peggio, tuttavia, se dimentichiamo di inizializzare una descrizione di classe prima di usarla. Di conseguenza in questo capitolo daremo un'occhiata ai meccanismi che automaticamente risolvono questo problema.

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend