Esiste un uso appropriato di #define per le costanti?

5

Su Internet vedo persone che promuovono l'uso di enum o const piuttosto che #define per la definizione costante.

Ci sono momenti in cui #define è più appropriato o ugualmente appropriato? Per favore, spiega.

Ci sono momenti in cui #define è semplicemente orribile? Si prega di elaborare. (Puoi dire "sempre" se lo desideri davvero, ma sto cercando risposte più specifiche.)

(Sì, sto cercando di giustificare il mio uso di #define, che a me sembra molto più ordinato.)

    
posta yodie 22.04.2011 - 19:19
fonte

4 risposte

9

Per semplificare: hanno ragione e ti sbagli.

Raramente c'è un buon motivo per usare #define per una costante in C ++. Sì, sono piuttosto orribili. In particolare, ignorano completamente gli ambiti per gli identificatori normali e hanno invece sempre l'ambito del file.

Puoi aggirare il problema (ad esempio, utilizzare i prefissi sui nomi che definisci per evitare collisioni) ma anche nel migliore dei casi non si adattano molto bene al resto della lingua.

Sospetto che tu stia pensando che sembra più ordinata è più una questione di assuefazione che di qualsiasi superiorità intrinseca - quando ho iniziato a spostarmi da C a C ++ tendevo a provare la stessa sensazione. Puramente intellettualmente ho potuto capire i punti che sono stati sollevati, ma emotivamente sembravano semplicemente sbagliati. Per un po 'ho pensato che fosse sciocco cambiare qualcosa che aveva funzionato e trovare per sempre. Ho dovuto davvero forzare me stesso a usare const invece, e all'inizio non ci credevo veramente - ma abbastanza velocemente non mi ci sono abituato, ma ho finito per ammettere che era davvero meglio.

    
risposta data 22.04.2011 - 19:35
fonte
7

In C, devi spesso usare #define . In C ++, puoi evitarlo.

Il problema con #define è che si tratta di una sostituzione testuale con ambito file. Non è possibile limitarne l'ambito. Se vuoi due diversi #define s per diverse parti del programma, non puoi metterli in spazi dei nomi diversi. Se stai #include di file di intestazione diversi con valori diversi per #define , devi assicurarti di ottenere l'ordine giusto. Se fai un #define di qualcosa che non è ovviamente un valore (come tutte le maiuscole), corri il rischio di rompere i programmi della gente in modi strani.

Quindi, se hai inviato una revisione del codice e ho visto un #define non necessario, chiederei di modificarlo e forse di inviarlo come difetto.

    
risposta data 22.04.2011 - 19:36
fonte
5

#define fa parte del pre-compilatore e dovrebbe essere trattato come tale. Dovrebbe essere usato solo per cambiare il comportamento del compilatore in base alle opzioni che stai passando ad esso (opzione di debug o opzione piattaforma per esempio), e più in generale la compilazione condizionale.

L'utilizzo di #define per le costanti utilizzate in-code crea in modo efficace una nuova parola chiave che interrompe qualsiasi incapsulamento (come gli spazi dei nomi). riferimento: Domande frequenti su C ++ . Questa violazione di incapsulamento che è un concetto OO di base è la ragione principale per cui le definizioni non sono popolari per la definizione di costanti in C ++.

    
risposta data 22.04.2011 - 19:38
fonte
1

Credo di essere un po 'vecchio di scuola considerando che NAMESPACE_CONSTANT non è molto diverso da Namespace::CONSTANT semanticamente. Mentre il primo ha tecnicamente un ambito più ampio e non è in namespace separati supportati dal compilatore, in pratica può essere considerato come tale, e gli scontri sono quasi sempre facilmente rilevabili e risolti. Il metodo define non sarebbe ancora usato da così tante persone se non funzionasse con software complesso.

Il problema è che spesso comporta REALLY_LONG_NAMESPACE_PREFIXES_FOR_EACH_VALUE, mentre spesso puoi lasciare lo spazio dei nomi anche per i nomi di costanti comuni con il metodo più recente. Ciò dà un grande impulso alla leggibilità.

L'altro vantaggio che non ho ancora visto è che l'uso di enum ti dà il controllo del tipo di compilatore. Questo è di grande aiuto se una "costante" ha valori diversi in contesti diversi, cosa che accade più spesso di quanto mi piacerebbe quando si lavora in un livello intermedio. Ancora una volta, puoi facilmente aggirare le interferenze nello spazio dei nomi aggiungendo prefissi alle tue definizioni, ma il compilatore non ti dirà se usi il prefisso sbagliato in una chiamata di funzione.

    
risposta data 22.04.2011 - 20:39
fonte

Leggi altre domande sui tag