Domanda

Perché gli oggetti oggettivi-C devono essere allocati dinamicamente? Perché devo renderlo un puntatore a un oggetto, a differenza di C ++ che posso crearli su Stack? Grazie.

È stato utile?

Soluzione

Il motivo principale: non sapere quanta dimensione dello stack riservare.

Le convenzioni e gli usi esistenti rendono anche il sollevamento della restrizione abbastanza difficile.

In questo caso la messaggistica dinamica non ha importanza, poiché l'impostazione della giusta "vtable" all'inizializzazione è banale.

In C ++, la dimensione di un oggetto stack è sempre conosciuta (e se è sbagliato, sai cosa aspettarti). Una sequenza di alloc/init OBJC può restituire uno dei diversi tipi - ciascuno con dimensioni diverse (è essenzialmente una fabbrica) o niente.

Le dimensioni possono anche variare in fase di esecuzione (ad esempio, è possibile aggiungere campi a una classe tramite il runtime).

Aggiornamento 1

Ero curioso di questo, quindi ho fatto un piccolo programma di test come prova del concetto.

Sono stato in grado di implementare una semplice gerarchia di classe OBJC basata su stack, che ha anche implementato un buon pezzo di NSObjectInterfaccia - Naturalmente, omettendo le interfacce di conteggio di riferimento e di allocazione dinamica in quanto non si riferiva alla prova del concetto. Ad ogni modo, la mia semplice gerarchia di classe era non Completamente compatibile con la classe o il protocollo NSObject, quindi non è qualcosa che dovrebbe essere usato in cui sono previsti tipi di NSObject, per ovvie ragioni. Pertanto, esso è Possibile (e non particolarmente difficile) farlo, se volevi davvero oggetti OBJC basati su stack.

Non devi fare nulla di diverso da C ++ per riservare lo spazio dello stack. La dimensione dello stack da riservare è ancora una restrizione in alcune aree (considera i metodi di fabbrica, i cluster di classe, ecc.).

Ci sono anche alcune funzionalità di runtime che non funzionano per impostazione predefinita. Il miglior esempio qui è la possibilità di aggiungere Ivars in fase di esecuzione. In effetti potresti accogliere questa funzionalità, se ne avevi bisogno. Non mi sono preoccupato di quell'esercizio.

Naturalmente, l'interfaccia di base potrebbe prendere diverse deviazioni: una deviazione che ho fatto per divertimento è stata aggiungere la possibilità di scambiare le implementazioni (tipo) di un oggetto vivente.

divertiti

Aggiornamento 2

A quanto pare, GCC accetta la prova del concetto che ho scritto. Sfortunatamente, questo è stato vietato in Clang a causa di problemi/pericoli che possono essere riscontrati nel riservarsi della dimensione corretta (considerando le caratteristiche dinamiche del linguaggio ...). Esempio: Clang proibisce sizeof(NSObject). Oh bene.

Altri suggerimenti

Obiettivo-C è un linguaggio dinamico, il che significa che tutto può cambiare in fase di esecuzione. L'oggetto di classe dell'oggetto viene creato solo quando viene caricato dall'eseguibile e può essere modificato per categorie. Inoltre, il runtime può istituire variabili per le proprietà. Poiché così tanto sull'oggetto può cambiare dopo la compilazione, non può essere creato fino a quando non viene utilizzato.

Ciò è dovuto al modo in cui Objective-C utilizza un legame dinamico o tardivo. A differenza di C ++ in cui avrai sempre la scelta tra chiamare una funzione di una classe per oggetto o tramite un puntatore della stessa classe o persino di una superclasse. In quest'ultimo caso è richiesto il polimorfismo.

Tuttavia, nell'obiettivo-C esiste sempre la capacità di determinare la funzione corretta in fase di esecuzione. La differenza è che, ad esempio in C ++, il compilatore deve garantire che esiste la funzione usata, mentre in Objective-C al compilatore non importa davvero, il sistema di runtime decide solo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top