Interessante pdf.
La mia prima domanda è, perché è ** cp costante? È necessario o semplicemente essere accurato in modo che lo scrittore di codice non faccia nulla di dannoso per l'incidente ?
E 'necessario quindi lo scrittore non fa nulla per caso, sì, e per comunicare qualcosa sulla natura del puntatore e il suo utilizzo per il lettore di del codice.
In secondo luogo, perché cp è un puntatore-a-un-puntatore (doppio asterisco?). La classe struct è stata definita a pagina 12 del pdf. Non capisco perché non può essere un puntatore singolo, dal momento che stiamo lanciando il puntatore automatico a un puntatore di classe, a quanto pare.
Date un'occhiata alla definizione di new()
(pg 13) in cui viene creato il puntatore p
(lo stesso puntatore che viene passato come self
-delete()
):
void * new (const void * _class, ...)
{
const struct Class * class = _class;
void * p = calloc(1, class —> size);
* (const struct Class **) p = class;
Quindi, 'p' è allocato spazio, poi dereferenziato e assegnato un valore puntatore (l'indirizzo in classe, questo è come il dereferenziamento e l'assegnazione a un puntatore int, ma invece di un int, stiamo assegnando un indirizzo). Ciò significa che la prima cosa in p è un puntatore alla sua definizione di classe. Tuttavia, a p è stato assegnato spazio per più di quello (terrà anche i dati di istanza dell'oggetto). Consideriamo ora delete()
ancora:
const struct Class ** cp = self;
if (self&&*cp&&(*cp)->dtor)
Quando cp è dereferenziato, dato che era un puntatore a un puntatore, ora è un puntatore. Cosa contiene un puntatore? Un indirizzo. Quale indirizzo? Il puntatore alla definizione di classe che si trova all'inizio del blocco puntato da p.
Questo è un po 'intelligente, perché p non è realmente un puntatore a un puntatore - ha una porzione più grande di memoria allocata che contiene i dati dell'oggetto specifici. Tuttavia, all'inizio di quel blocco c'è un indirizzo (l'indirizzo della definizione della classe), quindi se p è dereferenziato in un puntatore (tramite casting o cp), hai accesso a quella definizione. Quindi, la definizione della classe esiste solo in un posto, ma ogni istanza di quella classe contiene un riferimento alla definizione. Ha senso?Sarebbe più chiaro se p stata scritta come una struttura come questa:
struct object {
struct class *class;
[...]
};
Poi si potrebbe utilizzare qualcosa come p->class->dtor()
al posto del codice esistente in delete()
. Tuttavia, questo potrebbe rovinare e complicare l'immagine più grande.
In terzo luogo, in che modo un puntatore di vuoti viene modificato in un puntatore di classe (o puntatore del puntatore a puntatore di classe )? Penso che questa domanda most mostri la mia mancanza di di comprensione di C. Quello che immagino nella mia testa è un puntatore vuoto occupando una certa quantità di memoria, ma deve essere inferiore al puntatore Classe , perché una Classe ha un sacco di "roba" in esso.
Un puntatore è come un int - ha una piccola dimensione impostata per contenere un valore. Quel valore è un indirizzo di memoria. Quando si dereferenzia un puntatore (tramite *
o ->
), ciò a cui si accede è la memoria a quell'indirizzo. Ma dal momento che gli indirizzi di memoria sono tutti della stessa lunghezza (ad esempio, 8 byte su un sistema a 64 bit) i puntatori stessi hanno le stesse dimensioni indipendentemente dal tipo. È così che ha funzionato la magia del puntatore di oggetti "p". Per ripetere: la prima cosa nel blocco di memoria p
è un indirizzo, che gli permette di funzionare come un puntatore a un puntatore, e quando questo è dereferenziato, si ottiene il blocco di memoria contenente la definizione di classe, che è separato dai dati di istanza in p
.
@Joe Assolutamente nulla di sbagliato in questo. Buone capacità di programmazione in C sono così preziose e difficili da trovare in questi giorni di rapide sceneggiature. – jman
@Joe - Suppongo significhi ANSI C89, di cui si discute il nuovo libro di K & R. il codice nell'esempio non è K & R C IIRC. – Flexo
Sto leggendo K & R ANSI (penso dal 1989, come hai affermato). L'esempio di codice viene dal pdf OOC –