Programmazione orientata agli oggetti in ANSI-C. Funzioni per gli oggetti – Implementazione 1/2

Se scegliamo di sostituire il nome di una descrizione di classe come ad esempio Point da una chiamata alla funzione inizializzazione Point() per generare le descrizioni di classe in via automatica, dobbiamo modificare ogni utilizzo di una descrizione di classe e dobbiamo forzare i reports di ooc a generare file leggermente diversi.

I nomi delle descrizioni di classe sono usati in chiamate come new(), cast(), isA() e isOf() e nelle chiamate ai selettori delle superclassi. Usare funzioni al posto di variabili puntatori è una nuova convenzione, ossia dovremo modificare i programma applicativi e i file di implementazione. Un buon compilatore ANSI-C (o l'opzione -pedantic di GNU-C) può essere abbastanza d'aiuto, dovrebbe segnalare tutti i tentativi di passare un mome di funzione a parametri void *, ossia dovrebbe segnalare tutti quei punti nel nostro codice C dove abbiamo dimenticato di aggiungere una lista di argomenti vuota al nome della classe.

Cambiare i reports è un po' più complesso. E' utile guardare nei file generati per le descrizioni di classe. Il file di rappresentazione Point.r rimane invariato. Il file interfaccia Point.h dichiara i puntatori alle descrizioni di classe e metaclasse. Cambia da:

extern const void * Point;
extern const void * PointClass;

a

extern const void * const Point (void);
extern const void * const PointClass (void);

dove la parola chiave const in grassetto può essere usata solo in GNU-C. E' d'aiuto avere un report portabile così andiamo a modificare le linee interessate in h.rep così come segue:

extern const void * `%const `class (void); `n `n
extern const void * `%const `meta (void); `n `n
e aggiungiamo un nuovo report al file header comune header.rep
% const // GNUC supports const functions
`{if `GNUC 1 const `}

ooc definisce di solito il simbolo GNUC con un valore zero specificando:

$ ooc —DGNUC=1 ...

possiamo impostare questo simbolo a 1 sulla linea di comando per generare così un codice migliore.

Il file di implementazione Point.c contiene varie modifiche. Tutte le chiamate a cast() sono state cambiate: per la maggior parte esse sono prodotte dalle richieste %casts ad occ e di conseguenza dai report casts e checks così come mostrati nella sezione 8.4. Le altre chiamate a cast() sono usate in alcuni selettori e selettori di superclassi e nei costruttori di metaclassi, ma sono stati generati da report in etc.rep, c.rep, e c-R.rep. Ed ora ci possiamo rendere conto di quanto sia stato utile usare ooc per rafforzare la nostra codifica standard – lo standard è molto facile da cambiare in una sola posizione.

Il cambiamento significativo è però il nuovo stile di funzioni di inizializzazioni. Fortunatamente ci sono anche generate in c.rep e deriviamo la nuova versione convertendo Point così come mostrato nella sezione precedente ad un formato di report in c.rep. Infine, produciamo la funzione di default come segue:

const void * const Object (void) {
return & _Object;
}

attraverso il report init contenuto in c-R.rep, in modo che possa trarre beneficio dal condizionale GNUC per ooc. E' un po' roccambolesco perchè, come affermato nella sezione 7.5, l'inizializzazione statica di _Object deve essere codificata in Object.dc.

extern const struct Class _Object;
extern const struct Class _Class;
%init
static const struct Class _Object = {
{ MAGIC, & _Class },
"Object", & _Object, sizeof(struct Object),
Object_ctor, Object_dtor, Object_differ, Object_puto
};

Extern introduce le referenze future per le descrizioni, %init genera le funzioni le cui referenze sono state descritte sopra. Static, infine, dà un linkage interno alle descrizioni inizializzate, ossia esse sono ancora nascoste all'interno dell'implementazione di Object.c

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend