Usando C ++ ma non usando le caratteristiche specifiche del linguaggio, dovresti passare a C?


16

Sto sviluppando un emulatore NES come hobby, nel mio tempo libero. Uso C ++ perché è il linguaggio che uso principalmente, lo so soprattutto e mi piace soprattutto.

Ma ora che ho fatto qualche progresso nel progetto, mi rendo conto che non sto usando quasi nessuna caratteristica specifica di C ++, e avrei potuto farlo in C semplice e ottenere lo stesso risultato. Non uso modelli, sovraccarico dell'operatore, polimorfismo, eredità. Quindi cosa diresti? dovrei rimanere in C ++ o riscriverlo in C?

Non lo farò per ottenere prestazioni, potrebbe avere un effetto collaterale, ma l'idea è perché dovrei usare il C ++ se non ne ho bisogno?

Le uniche funzionalità di C ++ che sto usando sono le classi per incapsulare dati e metodi, ma ciò può essere fatto anche con strutture e funzioni, sto usando new ed delete, ma potrei anche usare malloc e free, e sono utilizzando l'ereditarietà solo per i callback, che potrebbe essere ottenuto con i puntatori alle funzioni.

Ricorda, è un progetto hobby, non ho scadenze, quindi i tempi di lavoro e il lavoro che richiederebbero una riscrittura non sono un problema, potrebbe anche essere divertente. Quindi, la domanda è C o C ++?


3
Mi sembra che tu abbia già risposto a te stesso: perché usare C ++ se hai solo bisogno di C? Ci sono molte situazioni in cui C è perfettamente OK.
Giorgio,

3
@Giorgio: E tutti evaporano dopo i primi sessanta secondi e devi mantenere il tuo codice.
DeadMG

7
I use C++ because is the language I use mostly, know mostly and like mostly.E questa è la risposta alla tua domanda. Dovresti cambiare lingua a metà progetto quando c'è un problema che la tua lingua attuale non può risolvere. I don't use templates, operator overloading, polymorphism, inheritance.Sarebbe molto più prezioso imparare e usare i concetti, piuttosto che passare a C. Dato che si tratta di un progetto hobby, perché non usare alcune cose che non hai mai usato prima? Puoi sempre iniziare un altro progetto in C e imparare la lingua, ma per il tuo progetto attuale non ha senso cambiare.
yannis,

4
Non uso nemmeno il 100% di una lingua in ogni progetto che scrivo. Conosci il C ++ nel modo migliore, potresti trovare buoni motivi per usare funzionalità per le quali non hai mai trovato un utilizzo prima. Si può iniziare a trattare C ++ come molto più sicuro C, una volta di iniziare a usare la roba libreria standard e costrutti Boost piace std::shared_ptr, std::unique_ptr, boost::scoped_ptr, std::vector, std::deque, std::map, ecc Per le funzioni di callback, sguardo l'uso di funtori, e in C ++ 11, si può anche iniziare a usare cose come le funzioni lambda.
wkl,

3
@Giorgio: Sì. Il rotolamento dell'elenco infinito collegato è destinato a produrre errori non necessari.
DeadMG

Risposte:


40

Non si sta utilizzando ora, ma la prossima volta che perdita di memoria o di ottenere una doppia eliminazione, sarete chiedendo di tornare std::vector<T>, std::unique_ptr<T, Del>e std::shared_ptr<T>, in grado di risolvere questi problemi facilmente- quasi banalmente. Questo è quello che succede a tutti coloro che usano C su C ++, alla fine, e quelli più intelligenti non aspettano che i bug vengano visualizzati prima di spostarsi.

Il codice che usa newe deletenon appartiene direttamente al C ++, appartiene a quel tipo di mezza casa che chiamiamo "C con classi". Ecco dove la lingua è stata circa 1985. Non è particolarmente simile al C ++, circa 2011. Con ogni probabilità, ovunque si è appreso C ++ semplicemente non insegnare qualcosa di molto ben che purtroppo è piuttosto common e con una migliore educazione, si sarebbe trova l'uso di queste funzionalità.

In particolare, come ho elencato sopra, le strutture di dati generici di C ++ e le classi di gestione delle risorse sono semplicemente sostanzialmente superiori a tutto ciò che C ha da offrire. Se si desidera un array allocato dinamicamente, utilizzare std::vector<T>. Questo è un caso d'uso piuttosto comune. Se non li stai usando, il tuo codice è enormemente a rischio di errore inutilmente, soprattutto in relazione alla gestione delle risorse. C ++ può garantire la sicurezza e riutilizzare il codice in un modo che C non potrà mai toccare.

Tuttavia, penso che potresti aspettarti troppo. Scrivere modelli e sovraccarichi degli operatori non è comune per i consumatori delle biblioteche. Se il codice viene utilizzato std::vector<T>, non è necessario scrivere un modello per farlo accadere. Se il codice viene utilizzato std::string, nessuno ti costringe a sovraccaricare i tuoi operatori. Devi solo fare queste cose per scrivere std::vector<T> e std::string- ma puoi comunque trarne il massimo vantaggio.

Il polimorfismo / ereditarietà ha anche solo un caso d'uso specifico. Se il tuo codice non ti richiede di scrivere alcun modello o utilizzare funzioni virtuali, allora non lo fa e ci sono programmi o segmenti di programmi in cui non è necessario scrivere i tuoi modelli.

Inoltre, non ci sono guadagni in termini di prestazioni in C su C ++.


1
@Giorgio: make_sharedesiste e puoi scrivere un make_uniquemodello banale che fa lo stesso lavoro. È più sicuro.
DeadMG

4
Bella risposta. Chiodo sulla testa. Il C ++ è molto prezioso per queste piccole librerie che dovremmo sempre usare.
Andres Jaan Tack,

2
@Giorgio: non è sicuro perché quando si chiamano più argomenti del genere, è possibile ottenere una perdita di memoria in caso di eccezione ed make_sharedè più efficiente. Solo le funzioni di fabbrica possono offrire una sicurezza delle eccezioni garantita.
DeadMG

6
@ tp1: WTF? In inglese per favore.
DeadMG

2
@Lohoris Non hai bisogno di una citazione per il buon senso. In che modo C dovrebbe essere più performante di C ++?
Chris dice di reintegrare Monica

7

Anche se non si utilizzano le funzionalità specifiche di C ++, un compilatore C ++ rileverà più problemi di uno C grazie al sistema di tipo C ++ più rigoroso.


6

Lo guarderei dall'altra parte. Vuoi guadagnare nulla per riscrivere il codice in C? Anche su un progetto puramente hobbistico, c'è un costo associato a una riscrittura del genere. Se nient'altro c'è quello che suppongo si chiamerebbe costo opportunità - cioè, le altre cose che avresti potuto fare in quel momento se non avessi perso tempo a riscriverlo in C.

In conclusione: a meno che non si pensi che il codice sia realmente utilizzato in alcuni ambienti in cui l'accesso al C ++ è veramente limitato (o inesistente), sarebbe una perdita inutile di tempo nella migliore delle ipotesi. Almeno nella mia esperienza, di solito va ben oltre molto rapidamente, ripensando al codice che ho scritto in C ++ doveva essere convertito in C, posso ricordare chiaramente che anche in parecchi casi in cui sembrava dovrebbe essere banale, stavo usando molte più funzioni specifiche per C ++ di quanto inizialmente immaginassi. Per avere molte speranze di essere utile, dovresti praticamente scegliere come target C89 / 90, nel qual caso ti verrà rapidamente ricordato cose come dover definire tutte le variabili all'inizio di un blocco invece che dove sono effettivamente Usato.

In breve, a meno che tu non sia abbastanza sicuro che riscrivere in C fornirà un vero vantaggio, ci sono quasi inevitabilmente cose molto migliori da fare.


+1 Qualche tempo fa ho dovuto scrivere una libreria per usarla in un altro progetto in C e ho pensato che fosse una buona idea implementarla anche in C, amico che stupido idiota ero allora.
Chris dice che ripristina Monica

1

Come risposta più generale:

Non passare a C ++ solo perché stai utilizzando alcune delle sue caratteristiche più uniche. Un giorno potresti aver bisogno di quelle funzionalità e ti batterai la testa perché stai usando C.


1

Per lo sviluppo di hobbisti, prenderei in considerazione il passaggio ai semplici linguaggi di tipo C. e C hanno maggiori probabilità di essere supportati su minuscoli moduli di sviluppo di hobby.

Molte delle risposte qui potrebbero provenire da tipi di software professionali. Come hobbista, non dovrai programmare continuamente o a tempo pieno. Quindi considera quale lingua è più probabile che ricordi o dimentichi le stranezze all'interno, se presenti il ​​tuo progetto per un anno e poi ritorni e prova a leggere il tuo codice dopo esserti arrugginito nella codifica. Il C ++, con un set di funzionalità più ricco, potrebbe richiedere più o meno tempo per riacquistare, a seconda del tuo stile di codifica.


1

Non è facile rispondere alle tue domande, poiché non sappiamo se stai lavorando al progetto per migliorare le tue abilità linguistiche specifiche (C vs C ++) o per migliorare altre capacità di programmazione (progettazione, risoluzione dei problemi, ecc.).

"Le uniche caratteristiche del C ++ che sto usando sono le classi per incapsulare dati e metodi, ma ciò può essere fatto anche con strutture e funzioni". Questo non è vero. structsin C non supportano l'incapsulamento e non possono contenere funzioni (metodi) - almeno non senza usare tecniche come i puntatori alle funzioni. Inoltre, le funzioni in C sono più deboli perché non possono essere sovraccaricate.

"Sto usando new ed delete, ma potrei anche usare malloc e free, e sto usando l'ereditarietà solo per i callback, che potrebbero essere raggiunti con i puntatori alle funzioni". Come menzionato deadmg, l'uso diretto newe deletein C ++ non è incoraggiato. Inoltre, l'ereditarietà IMHO (e GoF) in OOP dovrebbe essere preferita alla composizione solo quando è richiesto il polimorfismo. E non penso che sia banale ottenere il polimorfismo (associazione tardiva) in C usando i puntatori alle funzioni.

A parte questo, non cercherò di convincerti che C ++ sia "migliore" di C perché è una questione di preferenza e dipende sempre dal problema che stai cercando di risolvere (l'utilizzo delle funzionalità OOP per lo sviluppo dell'emulatore NES potrebbe essere una buona idea).


1
structsin C, infatti, può essere usato per incapsulare metodi. È sufficiente creare una struttura di puntatori a funzione e inizializzarli per puntare a qualsiasi funzione desiderata. Dai un'occhiata a lxr.linux.no/linux+v3.3/include/linux/fs.h#L1598 per un esempio.
Robert Martin,

Giusto. Grazie per il commento, ho esteso la risposta.
sakisk,

Bello. Ancora una volta: le funzioni in C possono essere sovraccaricate (pensate printf), ma così facendo perdete qualsiasi controllo del tipo. Non c'è modo di avere una serie finita di dichiarazioni accettabili: è 1 (e si ottiene il controllo del tipo) o "molti" (e si perde tutto il controllo del tipo, a grande rischio personale). Come con la maggior parte delle cose in C, è possibile ma spesso scomodo.
Robert Martin,

I puntatori alle funzioni sono una tecnica C avanzata? Veramente?
Donal Fellows

@DonalFellows Hai ragione, ho esagerato. Rimosso avanzato ... :)
sakisk

0

Sono un principiante, quindi ecco i miei 2 bit.

Sto imparando il C e il C ++ su Wibit.net con alcuni video di base di base, forse possono aiutarti molto a dare una visione d'insieme della "situazione" (non un annuncio!)

Ti consiglio di passare a C, solo per imparare, dato che sei un hobbista, questo sarà un piacere, non un problema.

Consiglio di più. Fallo in entrambe le lingue. Confronta il modo e le soluzioni che troverai e utilizzerai. Sono sicuro che non sarà "così facile" come ti aspetti ... ma sicuramente imparerai molto!


1
Grazie mille, ma non sto imparando, conosco già C e C ++, sto chiedendo quale utilizzare per questo specifico progetto.
Petruza,

oops, il mio tempo per imparare! = P
H_7,

1
Inoltre, consiglierei che al posto dei tutorial video, ottieni i libri di Kernigan e Stroustrup, un bel IDE (Visual Studio, Eclipse, Xcode) e impari codificando gli esempi, prova ed errore e ricorrendo allo stackoverflow.
Petruza,

-1

Ecco i pro e i contro di C ++ vs. C:

  1. Passare a C renderebbe più semplice rimanere all'interno del sottoinsieme C ++ scelto, perché il compilatore darebbe quindi un errore quando si esce da esso. Se il problema principale è rimanere all'interno di un sottoinsieme deciso, scegliere questa alternativa. (perché non abbiamo il supporto del compilatore per questo?)
  2. Una volta che puoi rimanere all'interno del sottoinsieme di funzionalità c ++ scelto, la prossima cosa da fare è provare a cambiare il sottoinsieme per eliminare le convenzioni errate che infrangono il codice. Ciò richiede l'uso dell'intero c ++.
  3. Una volta che hai sia "rimanere all'interno del sottoinsieme" che "è un buon sottoinsieme", spostati al di fuori delle funzionalità di c ++ e inizia a pensare ai requisiti.
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.