Sommario:
- Abilita tutti gli avvisi e i messaggi di errore
- Adotta uno stile di codifica chiaro e coerente
- Commenta il codice mentre lo scrivi
- Singolo passo ogni percorso nel debugger almeno una volta
- Limita la visibilità
- Tieni traccia della memoria heap
- Elimina i puntatori dopo aver eliminato ciò che indicano
- Usa le eccezioni per gestire gli errori
- Declare distruttori virtuali
- Fornire un costruttore di copie e un operatore di assegnazione sovraccarico
Video: Basically I'm Gay 2024
È spiacevole che passi più tempo a cercare e rimuovere i bug di quanti ne spenderai effettivamente scrivendo i tuoi programmi C ++ in primo luogo. I suggerimenti qui possono aiutare a ridurre al minimo il numero di errori che introduci nei tuoi programmi per rendere la programmazione un'esperienza più piacevole.
Abilita tutti gli avvisi e i messaggi di errore
La sintassi di C ++ consente un sacco di controllo degli errori. Quando il compilatore incontra un costrutto che non è in grado di decifrare, non ha altra scelta che emettere un messaggio. Prova a sincronizzare il backup con il codice sorgente (a volte meno che con successo), ma non genererà un eseguibile. Questo costringe il programmatore a correggere tutti i messaggi di errore.
Tuttavia, quando C ++ si imbatte in una struttura che può capire, ma la struttura odora comunque, C ++ genera un messaggio di avvertimento. Dato che C ++ è abbastanza sicuro che capisce ciò che vuoi, va avanti e crea un file eseguibile in modo che tu possa ignorare gli avvisi, se lo desideri. Infatti, se davvero non vuoi essere disturbato, puoi disabilitare gli avvisi.
Disabilitare o altrimenti ignorare gli avvertimenti è un'idea straordinariamente cattiva. È un po 'come staccare la spia del "motore di controllo" sul cruscotto dell'auto perché ti infastidisce. Ignorare il problema non lo fa andare via.
Adotta uno stile di codifica chiaro e coerente
La scrittura del codice C ++ in uno stile chiaro e coerente non solo migliora la leggibilità del tuo programma, ma porta anche a meno errori di codifica. Questo stato di cose alquanto sorprendente deriva dal fatto che il nostro cervello ha solo una quantità limitata di potenza di calcolo.
Quando leggi un codice che è pulito e ordinato e che segue uno stile che conosci, spenderai pochissima energia cerebrale analizzando la sintassi delle istruzioni C ++. Questo lascia più potere della CPU del cervello per decodificare ciò che il programma sta cercando di fare e non come lo sta facendo.
Un buon stile di codifica ti permette di fare quanto segue:
-
Distinguere tra nomi di classi, nomi di oggetti e nomi di funzioni
-
Capire cosa viene usata per la classe, la funzione o l'oggetto, in base al suo nome
-
Differenzia i simboli del preprocessore dai simboli C ++ (ovvero, #define gli oggetti dovrebbero risaltare)
-
Identifica i blocchi del codice C ++ allo stesso livello (questo è il risultato di un rientro coerente)
In Inoltre, è necessario stabilire un formato standard per le intestazioni del modulo che fornisce informazioni sulle funzioni o classi in ciascun modulo, l'autore, la data, la versione e qualcosa sulla cronologia delle modifiche.
Tutti i programmatori coinvolti in un singolo progetto dovrebbero usare lo stesso stile di codifica. Un programma scritto in un mosaico di diversi stili di codifica è confuso e non professionale.
Commenta il codice mentre lo scrivi
Puoi evitare errori se commenta il tuo codice mentre lo scrivi, piuttosto che aspettare fino a quando tutto funziona e quindi tornare indietro e aggiungere commenti.
La formulazione di commenti ti costringe a fare il punto su ciò che stai cercando di fare. Brevi commenti sono illuminanti, sia quando li leggi più tardi, sia quando li stai scrivendo. Scrivi commenti come se parlassi con un altro programmatore esperto.
Singolo passo ogni percorso nel debugger almeno una volta
Come programmatore, devi capire cosa sta facendo il tuo programma. Non è sufficiente che il programma restituisca il valore atteso. Devi capire tutto ciò che sta facendo il tuo programma. Niente ti dà una sensazione migliore di quello che sta succedendo sotto il cofano di single-stepping il programma, eseguendolo passo dopo passo con un buon debugger (come quello che viene fornito con Code:: Blocks).
Oltre a ciò, mentre esegui il debug di un programma, hai bisogno di materiale grezzo per capire un comportamento bizzarro che potrebbe emergere durante l'esecuzione del programma. Niente ti dà quel materiale meglio di un singolo passaggio attraverso ogni funzione al suo ingresso in servizio.
Infine, quando una funzione è finita e pronta per essere aggiunta al programma, ogni percorso logico deve essere percorso almeno una volta. I bug sono molto più facili da trovare quando si esamina la funzione da sola piuttosto che dopo che è stata gettata nel piatto con il resto delle funzioni - da allora, la tua attenzione è passata a nuove sfide di programmazione.
Limita la visibilità
Limitare la visibilità degli interni di classe al mondo esterno è una pietra miliare della programmazione orientata agli oggetti. La classe dovrebbe essere responsabile per il suo stato interno - se qualcosa si fa rovinare nella classe, allora è colpa del programmatore di classe. Il programmatore dell'applicazione dovrebbe preoccuparsi di risolvere il problema in questione.
In particolare, visibilità limitata significa che i membri dei dati non dovrebbero essere accessibili al di fuori della classe, ovvero dovrebbero essere contrassegnati come protetti. Inoltre, le funzioni membro di cui il software applicativo non ha bisogno di essere informato dovrebbero essere contrassegnate come protette. Non esponete più interni della classe del necessario per portare a termine il lavoro.
Tieni traccia della memoria heap
La perdita della memoria heap è la fonte più comune di errori fatali nei programmi rilasciati sul campo e, allo stesso tempo, il problema più difficile da individuare e rimuovere. (Poiché questa classe di errori è così difficile da trovare e rimuovere, è prevalente nei programmi che si acquistano.) Potrebbe essere necessario eseguire un programma per ore prima che i problemi inizino a sorgere (a seconda di quanto è grande la perdita di memoria).
Come regola generale, i programmatori dovrebbero sempre allocare e rilasciare la memoria heap allo stesso "livello". "Se una funzione membro MyClass:: create () assegna un blocco di memoria heap e lo restituisce al chiamante, allora dovrebbe esserci un membro MyClass:: release () che lo restituisce all'heap.In particolare, MyClass:: create () non dovrebbe richiedere la funzione genitore per rilasciare la memoria.
Se possibile, MyClass dovrebbe tenere traccia di tali indicatori di memoria da solo ed eliminarli nel distruttore.
Elimina i puntatori dopo aver eliminato ciò che indicano
Assicurati di azzerare i puntatori dopo che non sono più validi; lo fai assegnandogli il valore nullptr. Le ragioni di questa azione diventano chiare con l'esperienza: puoi continuare a usare un blocco di memoria che è stato restituito all'heap e nemmeno saperlo. Un programma potrebbe funzionare ben il 99% delle volte, rendendo molto difficile trovare l'1% dei casi in cui il blocco viene riallocato e il programma non funziona.
Se si annullano i puntatori non più validi e si tenta di utilizzarli per memorizzare un valore (non è possibile memorizzare nulla in corrispondenza o in prossimità della posizione nullo), il programma si bloccherà immediatamente. Crashing suona male, ma non è se espone un problema. Il problema è lì; è solo una questione se lo trovi o meno prima di metterlo in produzione.
Usa le eccezioni per gestire gli errori
Il meccanismo di eccezione in C ++ è progettato per gestire gli errori in modo comodo ed efficiente. In generale, devi lanciare un indicatore di errore piuttosto che restituire un flag di errore. Il codice risultante è più facile da scrivere, leggere e gestire. Inoltre, altri programmatori se lo aspettano e non vorresti deluderli, vero?
Limita l'uso delle eccezioni agli errori veri. Non è necessario generare un'eccezione da una funzione che restituisce un indicatore "non funzionante" se questa è una parte della vita quotidiana per quella funzione.
Declare distruttori virtuali
Non dimenticare di creare un distruttore per la tua classe se il costruttore alloca risorse come la memoria heap che deve essere restituita quando l'oggetto raggiunge la sua morte definitiva. Dopo aver creato un distruttore, non dimenticare di dichiararlo virtuale.
"Ma," tu dici, "la mia classe non eredita da nulla e non è sottoclassata da un'altra classe. "Sì, ma potrebbe diventare una classe base in futuro. A meno che tu non abbia una buona ragione per non dichiarare il distruttore virtuale, fallo quando crei la classe.
Fornire un costruttore di copie e un operatore di assegnazione sovraccarico
Se la classe ha bisogno di un distruttore, ha quasi sicuramente bisogno di un costruttore di copie e di un operatore di assegnazione sovraccarico. Se il costruttore assegna risorse come la memoria heap, l'operatore predefinito di costruzione e assegnazione delle copie non farà altro che creare scompiglio generando più puntatori alle stesse risorse.
Quando viene richiamato il distruttore per uno di questi oggetti, ripristinerà le risorse. Quando arriva il distruttore per l'altra copia, rovinerà tutto.