
Implementare la classe Object è di immediata realizzazione: il costruttore e il distruttore ritornano self e differ() controlla che i suoi puntatori che fungono da argomenti siano uguali. Definire queste implementazioni anche se triviali è comunque importante, tuttativa useremo un albero semplice di classi e faremo in modo che Object sia l'ultima superclasse di ogni altra classe; se una classe non sovrascrive un metodo come differ() lo eredita da Object, ossia ogni classe ha almeno una definizione rudiementale per ogni metodo dinamicamente linkato già applicabile a Object.
Questo è un principio generale: qualora andassimo a introdurre un nuovo metodo linkato dinamicamente, lo andremo immediatamente ad inplementare per la sua prima classe. In questo modo non andremo mai a selezionare un metodo totalmente non definito. Un esempio potrebbe essere il metodo puto() per Object:
static int Object_puto (const void * _self, FILE * fp) { const struct Class * class = classOf(_self); return fprintf(fp, "%s at %p\n", class —> name, _self); }
Ogni oggetto punta a una descrizione di classe e abbiamo memorizzato il nome della classe con la descrizione. Di conseguenza, per ogni oggetto possiamo mostrare come minimo il nome della classe e l'indirizzo dell'oggetto. Le prime tre linee di output ricavate da questo semplice programma di test (in riferimento alla paragrafo 6.4) indicano che non abbiamo sovrascritto questo metodo per Class o Any.
Puto() si basa sulla funzione di accesso classOf() che effettua alcuni controlli di sicurezza e restituisce il descrittore di classe per un oggetto:
const void * classOf (const void * _self) { const struct Object * self = _self; assert(self && self —> class); return self —> class; }
Analogamente, possiamo chiedere la dimensione di un oggetto – da ricordare che tecnicamente un oggetto è un semplice void* in ANSI C.
size_t sizeOf (const void * _self) { const struct Class * class = classOf(_self); return class —> size; }
Si può discutere sul fatto di domandare direttamente ad un oggetto la propria dimensione, oppure se dovremmo chiedere piuttosto la classe dell'oggetto e poi chiedere la dimensione alla classe. Se implementassimo sizeOf() per gli oggetti, non potremmo applicarlo ad una descrizione di classe per ottenere la corrispondente dimensione di un oggetto – otterremo la dimensione della descrizione di classe e null'altro. Tuttavia, l'uso pratico indica che definire sizeOf() per gli oggetti è di gran lunga preferibile. Al contrario, super() è un metodo linkato staticamente che restituisce la superclasse di una classe, non un oggetto.
