Esiste una convenzione di capitalizzazione comune in C ++? [chiuso]


13

Faccio molto lavoro in Python e Java, ed entrambi questi linguaggi hanno convenzioni abbastanza comuni (anche se non universali) su come usare le maiuscole negli identificatori: entrambi usano PascalCaseper nomi di classe e ALL_CAPSper costanti "globali", ma per altri identificatori un utilizza molto codice Java mixedCasementre utilizza molto codice Python underscore_delimiters. So che nessuna lingua o biblioteca applica alcuna particolare capitalizzazione, ma ho scoperto che quando mi attengo alle convenzioni standard per la lingua che sto usando, il mio codice sembra molto più leggibile.

Ora sto iniziando un progetto in C ++ e vorrei applicare la stessa idea. C'è qualche convenzione più comune per la capitalizzazione che dovrei conoscere?


Il problema con camelCase è che non gioca bene con il preprocessore. Non è un grosso problema, soprattutto perché il preprocessore di solito può essere evitato.
Pubblicazione

Ho dovuto affrontare questa decisione solo pochi giorni fa. Alla fine, è stato un gioco da ragazzi, dal momento che sia la libreria standard che boost usano underscore_lowercase_delimiters. Dal momento che uso boost come booster STL, sarà tutto cosparso del mio codice. Altre librerie che utilizzo che sono PascalCase (SFML) possono essere più facilmente contenute, quindi ogni dato metodo è piuttosto standard.
Max

@ Pubby8: per curiosità: come fa camelCase a scontrarsi con il preprocessore?
Joachim Sauer,

@JoachimSauer Le singole parole in camelCase possono avere un caso diverso, ma le macro non possono cambiare maiuscole e minuscole. Questo diventa un problema se vuoi una macro che prende parte di una parola come argomento - potresti dover fornire entrambi i casi come argomenti: macro (x, X). È un problema piuttosto piccolo, ma dovrebbe essere noto se si intende utilizzare il preprocessore.
Pubblico,

Risposte:


27

C'è qualche convenzione più comune per la capitalizzazione che dovrei conoscere?

Il C ++ si basa sul C, che è abbastanza vecchio da aver sviluppato un sacco di convenzioni di denominazione al momento dell'invenzione del C ++. Quindi C ++ ne ha aggiunti alcuni e C non è stato inattivo nemmeno pensando a nuovi. Aggiungete a ciò i molti linguaggi derivati ​​dal C, che hanno ulteriormente sviluppato le convenzioni di denominazione in C del loro inventore, al punto da fecondare di nuovo su C e C ++ ... In altre parole: C ++ non ha una, ma molte di tali convenzioni.

Tuttavia, se stai cercando una convenzione di denominazione, potresti anche guardare la convenzione di denominazione della libreria standard , perché questa è l'unica che tutti gli sviluppatori C ++ dovranno conoscere e a cui saranno abituati.

Tuttavia, qualunque sia la regola più importante che usi è: sii coerente!

È interessante notare che, mentre ho iniziato con un mix di PascalCase e camelCase, e sono stato coinvolto in numerosi progetti con convenzioni di denominazione ancora più numerose, nel corso degli anni ho scoperto che mi sono bloccato sempre più con lo standard_library_convention. Non chiedermi perché.


Grazie per le informazioni ... quindi la libreria standard è sottolineata, allora? (almeno più di ogni altra cosa?) Stavo pensando in questo senso, ma era un po 'difficile da dire a causa di cose come iostream in cui metà dei nomi dei metodi sembrano essere lo stesso tipo di frammenti di parole uniti come ANSI C :-P
David Z,

5
@David: la libreria di iostreams ha probabilmente 25 anni e (fatta eccezione per la libreria C o il corso) potrebbe essere la parte più vecchia della libreria standard C ++. Si spera che nessuno nella loro mente giusta lo progetterebbe così com'è oggi e, auspicabilmente, anche quelli che non sono nella loro mente giusta non sceglierebbero gli identificatori nel modo in cui vengono utilizzati nella libreria dei flussi. (Dai, ci sono funzioni nominate egptr, sputne uflowanche così underflow. È semplicemente esilarante!) Comunque, sì, la libreria std al giorno d'oggi usa all_lowercase_with_underscores.
sbi,

@sbi Ho scoperto che la libreria iostream non è più considerata una libreria standard per C ++. E come hai detto, i suoi identificatori non sono utili come convenzione di programmazione ;-)
umlcat,

2
@umlcat: la libreria iostreams (nel suo modello da accettata per C ++ 03) è sicuramente considerata parte della libreria standard C ++.
sbi,

Ho anche seguito la stessa strada. Penso che la ragione per cui ho è camelCase sia leggermente più facile da scrivere e volevo essere pigro lì. In seguito ho appreso che ho trascorso più tempo a leggere e refactoring il mio codice piuttosto che a scriverlo, e snake_case è più facile da leggere. Quindi si tratta di ridurre al minimo il dispendio energetico. Ora sto giocando con l'uso di nomi minuscoli per le lezioni. Non è convenzionale, tuttavia penso che cambiarlo e mettere in rilievo le Istanze importanti e i tipi con lettere minuscole in realtà migliora la leggibilità del mio codice. Sto pensando che forse questa è la strada da percorrere. Ciò che è importante è maiuscolo, come in umanese.
PSkocik,

19

Concordiamo innanzitutto che TUTTO IL MAIUSCOLO è un pugno nell'occhio e dovrebbe essere ridotto al minimo.

In C e C ++ è quindi usato come convenzione per le macro e solo per le macro, perché le macro sono ugualmente brutte, per non dire male.

I primi C non avevano const, quindi le costanti dovevano essere espresse come macro. Inoltre, in quei primi programmi i programmi erano molto più brevi, in modo che le pratiche oggi non buone potessero essere usate (ad es. IIRC Brian Kernighan ha scritto codice con molte macro non maiuscole). Inoltre, a quei tempi esistevano tastiere che non avevano lettere minuscole; Ne ho usato uno, sul computer norvegese Tandberg EC-10, circa 1980 o 1979, credo.

Quindi, Java raccolse la convenzione maiuscola per le costanti dai primi anni del C. Nel frattempo, e forse anche prima (non sono sicuro della cronologia qui), C ottenne costanti. Tuttavia, mentre ovviamente alcuni / molti programmatori C erano bloccati nella precedente convenzione per necessità di costanti come macro maiuscole, i programmatori C ++ erano più sensibili.

Il grande problema al giorno d'oggi è quando le persone vengono prima insegnate a Java, o prima a C (con convenzioni dal Medioevo), e poi arrivano al C ++, prendendo con loro quella pessima convenzione maiuscola.

Così,

    int const answer = 42;    // Nice, good, OK.
    const int ANSWER = 0x2A;  // Ouch!
    #define COMPANYNAME_ANSWER 052  // Oh kill me, please.

Beh, potresti aver pensato di aver citato solo tastiere maiuscole. Oh no Perché questa è semplicemente la più antica, la più arcaica limitazione tecnologica che ha guidato le convenzioni di denominazione, o almeno ha influenzato quanto sembravano sbagliate / giuste. Successivamente, c'era il problema della trasmissione seriale a 7 bit, che causava corrispondenti problemi con i codici carattere (codifiche di caratteri di newspeak) utilizzati, il che significava che dovevi limitarti alle lettere dell'alfabeto inglese, dalla A alla Z.

In realtà consiglio di farlo ancora. Ecco dove siamo! Non abbiamo oltre.

Al momento, a partire dal 2011, lo standard C ++ supporta Unicode generale nei nomi (e lo fa dal 1998), mentre le attuali implementazioni C ++ no. In particolare il compilatore g ++ è un personaggio nazionale sfidato. Deriva da quel limite tecnologico dell'età oscura.

Così,

    double blueberryJamViscosity  = 0.0;    // OK
    double blåbærsyltetøyViskositet = 0.0;  // Ouch!

Infine, in materia di caratteri di sottolineatura rispetto a lettere maiuscole intervallate,

  • Prenota un modulo facilmente riconoscibile per i nomi dei tipi.
  • Prenota TUTTO MAIUSCOLO per le macro.
  • Sii coerente.

Penso che sia, in realtà, ad eccezione di regole come "generalmente evita il nome di una sola lettera tranne (loop, template param, blah blah)", e "evita di usare l, facilmente confuso con 1" ed "evita maiuscole O, facilmente confuso con 0 ". Inoltre, ovviamente, evita di usare nomi riservati come iniziare con il carattere di sottolineatura seguito da caratteri maiuscoli, contenente due caratteri di sottolineatura successivi, o iniziare con il carattere di sottolineatura e trovarti nello spazio dei nomi globale.

Saluti e hth


Alf, ISTR Stroustrup menzionato nella copia di D&E C constda C ++, quindi questo deve essere successo molto tempo fa e molto prima di Java, probabilmente per C89.
sbi,

2
Oh, e un sentito cuore +1per "Sii coerente!" Leggendolo mi chiedo perché ho dimenticato di menzionare questa, la più importante, regola nella mia risposta, quando era quella che non ho mai dimenticato di dire ai miei studenti. Suppongo che mi perdonerai se ora lo aggiungo alla mia risposta come ripensamento?
sbi,

2

Di solito tendo a rispettare la convenzione che vedo di più nei codebase esistenti per la lingua. Nel caso di C ++, di solito vedo camelCase. Nel caso di Ruby o PHP di solito vedo stuff_like_this.

Realisticamente parlando, tuttavia, la cosa più importante è che scegli una convenzione di stile che non sia del tutto folle (dOnT_dO_tHiS) e sia coerente con essa. Fallo in modo che lo stile non cambi in tutto il codice per un particolare progetto. Se stai lavorando a un progetto esistente, ti consigliamo di seguire lo stile già presente.


1

Bene, c'è un sistema ungherese che è davvero comune anche adesso, ma preferirei tagliarmi la gola piuttosto che raccomandarlo. App Ungherese è migliore in quanto i suoi segni annotativi sono veramente indicativi della semantica, anche se ritengo che sia un po 'troppo appassionato di abbreviazioni quando una parola breve farebbe. (Per usare l'esempio da quella pagina di Wikipedia, perché usare rwper riga quando rowc'è solo un carattere in più? Non è come se ci fosse una carenza vocale globale).

Realisticamente, la cosa più importante è seguire le convenzioni delle persone con cui stai lavorando . Veramente. La maggior parte delle convenzioni funziona abbastanza bene, soprattutto se utilizzata in modo coerente. L'incoerenza è la peggiore (ancor più dei sistemi ungheresi, che odio). E se sei da solo, usa quello che vuoi.


1

Da quello che ho visto, varia tra i progetti.

I caratteri di sottolineatura incorporati sono probabilmente più tradizionali / più comunemente usati in C su Unix. Anche la libreria standard segue questo, quindi dovrebbe quasi sicuramente essere trattata come impostazione predefinita, da usare a meno che non ci sia abbastanza codice esistente che utilizza un'altra convenzione per forzare assolutamente l'uso di quell'altra convenzione.

Windows (per un esempio) usa la custodia per cammelli per la maggior parte delle sue funzioni, quindi alcune persone che sviluppano per Windows fanno lo stesso. Questo è anche abbastanza comune tra le persone che sono davvero più abituate ad altre lingue e cercano di trattare il C ++ come se fosse solo una strana variante di qualcos'altro.


1

Ho usato sia la libreria standard che boost come riferimenti per le convenzioni di denominazione. Tuttavia, c'è un problema con questa soluzione.

La libreria standard utilizza una convenzione di denominazione progettata per tentare di ridurre le collisioni con il codice. Parte della soluzione consiste nell'utilizzare tutte le lettere minuscole. Da qui l'uso di underscore invece di camelCase.

Trovo che camelCase sia leggibile. PascalCase è spesso usato per i nomi di classe in quanto rappresenta l'equivalente di un nome proprio. Tuttavia, infrangerò questa regola per i funzioni che sono più rappresentativi di un verbo.

Cerco di non usare le macro. Tuttavia, quando lo faccio, le macro sono fatte per apparire come funzioni quando possono. Uso anche valori const o enum anziché costanti manifest, evitando ulteriormente tutte le maiuscole. In genere, prefisso questi simboli con una 'k' per indicare che sono costanti.

// instead of a manifest constant
#define HOURS 24

// use const
const int kHours = 24; 

// or enum
enum {
    kHours   = 24,
    kMinutes = 60
};

0

Questo riferimento descrive una convenzione di denominazione che è abbastanza simile a quella che ho visto usato con successo in almeno tre società per cui ho lavorato in passato.

Contrariamente a una risposta precedente, eviterei di seguire la convenzione di denominazione della libreria standard C ++ nel mio codice, se non altro per evitare collisioni di nomi con la libreria standard.

Anche la precedente risposta SO su un argomento correlato potrebbe essere interessante: /programming/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier


Umm, puoi usare la stessa convenzione di denominazione senza usare gli stessi nomi ... e se vuoi davvero gli stessi nomi, sei comunque protetto da spazi dei nomi, ad es . std::stringVs. gnawme::string
einpoklum,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.