2011-01-14 11 views
6

So qual è la differenza e come funzionano entrambi, ma questa domanda riguarda più lo stile di codifica.Puntatore contro variabile nella classe

Ogni volta che sto codificando faccio molte classi, tutte hanno variabili e alcune di esse sono puntatori e alcune sono variabili normali. Io di solito preferisco le variabili a puntatori se che i membri dura quanto la classe fa, ma poi il mio codice diventa in questo modo:

engine->camera.somevar->x; 
// vs 
engine->camera->somevar->x; 

Non mi piace il puntino nel mezzo. O con variabili private:

foo_.getName(); 
// vs 
foo_->gatName(); 

Penso che il punto "scompare" in un lungo codice. Trovo che -> sia più facile da leggere in alcuni casi.

La mia domanda sarebbe se si usano puntatori anche se la variabile verrà creata nel costruttore e cancellata nel distruttore? C'è qualche consiglio di stile in questo caso?

P.S. Penso che il punto sia migliore in alcuni casi.

risposta

5

Prima di tutto è una cattiva forma per esporre le variabili membro.

In secondo luogo la tua classe probabilmente non dovrebbe mai contenere i puntatori.

Lievi corolary: classi che contengono logica di business non dovrebbe mai avere puntatori (in quanto questo significa che contengono anche il codice di gestione del puntatore e il codice di gestione del puntatore dovrebbero essere lasciati a classi che non hanno la logica di business, ma sono stati progettati specificamente per lo scopo di puntatori gestione (puntatori intelligenti e contenitori)

Le classi di gestione puntatore (puntatori/contenitori intelligenti) devono essere progettate per gestire un singolo puntatore. Gestirne più di una è molto più difficile di quanto si pensi e non devo ancora trovare una situazione in cui Complessità extra pagata

Infine i membri pubblici non dovrebbero esporre l'implementazione sottostante non fornire accesso ai membri nemmeno tramite getter/setter). Questo vincola l'interfaccia strettamente all'attuazione. Invece la tua interfaccia pubblica dovrebbe fornire una serie di azioni che possono essere eseguite sull'oggetto. cioè i metodi sono verbs.

In C++ è raro vedere puntatori.
Sono generalmente nascosti all'interno di altre classi. Ma dovresti abituarti a usare una miscela di -> e . poiché tutto dipende dal contesto e da ciò che stai cercando di trasmettere. Finché il codice è pulito e leggibile, non importa troppo.

A addendum personale:

io odio il _ ad allora fine del tuo identificativo che rende il. disapear foo_.getName() Penso sarebbe un aspetto molto meglio come foo.getName()

+0

Bene, ma per quanto riguarda i membri rispetto ai puntatori intelligenti (nel codice di implementazione)? – user396672

+0

@ user396672: che dire di loro. Un puntatore intelligente è solo un oggetto come un altro. Il suo compito è gestire un singolo puntatore. –

+0

beh, alcune classi hanno variabili pubbliche e non vedo alcun motivo per renderle private. Creo solo variabili private se il lavoro di classe può essere danneggiato da un uso non valido di esse. Se sono nella classe solo per rendere più gradevole la struttura del programma - perché no? Ad esempio l'esempio con il motore. Quando codifico un gioco (a volte faccio giochi di merda. È molto divertente), creo un "motore" di puntatore esterno perché viene usato da molti altri oggetti. E quel motore di solito contiene cose come la macchina fotografica in ambito pubblico. Lo faccio perché altri oggetti devono accedere alla classe della telecamera e non possono rovinare il motore. – Pijusn

0

Se la struttura "incorporata" ha esattamente la stessa durata della struttura "genitore" e non viene referenziata da nessun'altra parte, preferisco averla come membro, piuttosto che usare un puntatore. Il codice prodotto è leggermente più efficiente, poiché salva un numero di chiamate nell'allocatore di memoria ed evita un numero di riferimenti ai puntatori.

È anche più facile da gestire, poiché la possibilità di errori relativi ai puntatori è ridotta.

Se, d'altra parte, c'è la minima possibilità che la struttura incorporata possa essere referenziata da qualche altra parte, preferisco usare una struttura e puntatori separati. In questo modo non dovrò refactoring il mio codice se si scopre che la struttura incorporata deve essere estratta dal suo genitore.

EDIT:

immagino che significa che di solito vado con il puntatore alternativa :-)

EDIT 2:

E sì, la mia risposta è supponendo che si vuole veramente (o hanno) per scegliere tra i due, ovvero scrivere codice in stile C. Il modo corretto orientato agli oggetti per accedere ai membri della classe è attraverso le funzioni get/set.

I miei commenti sull'opportunità di includere un'istanza di classe effettiva o un puntatore/riferimento a uno sono probabilmente ancora validi, tuttavia.

+0

membri, tuttavia, possono portare a grandi oggetti e causare problemi di frammentazione della memoria a comparire – user396672

0

Idealmente, non si dovrebbe usare neanche: si dovrebbero usare i metodi getter/setter. Il risultato della performance è minimo (il compilatore probabilmente lo ottimizzerà comunque).

La seconda considerazione è che l'utilizzo dei puntatori è un'idea generalmente pericolosa, perché a un certo punto è probabile che si rovini tutto.

Se nessuno di questi ti turba, allora direi che tutto ciò che rimane è una questione di preferenze personali.

+2

getter/setter è un cattivo design in quanto espone l'implementazione e quindi ti accoppia ad esso (è meno accoppiato che esponendo th e variabili ma lascia ancora molto a desiderare). –

+0

Cosa lascia a desiderare che non è contemplato in questo, per esempio? http://stackoverflow.com/questions/2747721/getters-and-setters-are-bad-oo-design In altre parole, perché ritieni che non ci sia MAI una situazione in cui sono utili? – Kricket

+0

Mai dire mai. L'articolo che colleghi e quello che collega anche l'argomento in dettaglio. Ma si riduce all'accoppiamento. Più il tuo codice è accoppiato, più difficile sarà il mantenimento e/o la modifica/l'aggiornamento. I getter/setter introducono un ulteriore accoppiamento che non è generalmente necessario. –

1

Non si dovrebbe fare la vostra scelta, perché a trovare '->' più facile da leggere :) utilizzando una variabile membro di solito è meglio come non si può sbagliare con te puntatore.

Detto questo, l'utilizzo di una variabile membro ti obbliga a esporre la tua implementazione, quindi devi usare i riferimenti. Ma poi devi inizializzare nel tuo costruttore, che non è sempre possibile ...

Una soluzione è usare std :: auto_ptr o boost :: scope_ptr di un puntatore intelligente simile. Lì otterrete il vantaggio di entrambe le soluzioni, con pochissimi inconvenienti.

MY2C

EDIT:

alcuni link utili:
Article on std::auto_ptr
boost::scoped_ptr
Pimpl : private implementation

Problemi correlati