È una buona abitudine usare le espressioni C nel codice C ++?


19

A scuola abbiamo iniziato a studiare C quest'anno, nonostante io sia molto più avanti della lezione, e ho imparato Java, C ++ e C mentre la classe è alla base di C. Comunque, mi sono documentato, leggendo libri, articoli e ho chiesto alla mia insegnante perché dovrei imparare il C, e lei ha detto che era il fondamento del C ++. Quando ho iniziato a programmare ho scoperto che il C ++ era molto più semplice, in seguito ho imparato C. Ma nei libri puoi vedere che il codice C funziona in C ++ ma non va viceversa.

La mia domanda è piuttosto semplice ~ È una buona abitudine usare le espressioni C in C ++? Lasciate che vi faccia un esempio:

Dovrebbe questo codice

#include <stdio.h>
#include <iostream>

int main() {
int x;
scanf("%d", &x);
cout << "The number you entered is " << x << "And it's double is " << x*x;
return 0;
}

Sii più efficiente o migliore in qualsiasi modo di questo:

#include <iostream>

int main() {
int x;
cin >> x;
cout << "The number you entered is " << x << "And it's double is " << x*x;
return 0;
}

Ho già fatto una semplice documentazione su questo in alcuni vecchi libri polverosi, e da quello che ho trovato, usare scanf invece di cout scarica anche il flusso o qualcosa del genere, quindi in pratica sto chiedendo se è meglio usare scanf e in quali contesti.

Questo vale anche per il file IO poiché ho sempre trovato FIle IO più facile in C che in C ++. Questa domanda vale praticamente per ogni espressione generale in C applicata a C ++. È anche degno di nota il fatto che sto usando un compilatore moderno e tuttavia questo non dovrebbe importare poiché sto chiedendo se è una buona abitudine di programmazione usare espressioni C nel codice C ++.

Probabilmente ci sono svantaggi e svantaggi di farlo, ma sto solo cercando un tipo di risposta sì / perché, no / perché.

Inoltre, se ci sono dei dettagli che ho lasciato fuori, pubblica un commento.


12
Fai molta attenzione al mixaggio stdioe iostream. C'è un certo ordine e sincronizzazione garantiti all'interno di una famiglia che non si applicano necessariamente al di fuori di esso.
David Thornley,

Grazie per il suggerimento, ma lo scrap del codice è stato un puro esempio. Grazie comunque.
Bugster,

25
Se stai imparando la programmazione; Devi imparare il rientro corretto!
maschera di bit

5
scanf () non è un ottimo esempio; è così terribilmente soggetto a errori da usare che consiglierei di evitarlo in C o C ++.
Russell Borogove,

1
Avrebbe potuto essere il codice di esempio soltanto, ma il commento di David diventa veramente al cuore del problema perché si dovrebbe non usare linguaggi C durante la programmazione in C ++. Sono lingue completamente diverse; non confonderli più di quanto tu confonda Java e C, o C ++ e Visual Basic.
Cody Grey,

Risposte:


36

No, è una cattiva abitudine. Quando lo fai per vivere, probabilmente finirai per violare le guide di stile a cui il tuo team aderisce (o almeno verrai colpito durante le revisioni del codice).

Sì, funziona, ma se esiste un equivalente c ++, usalo. (ad esempio, cercare di non mescolare printfscon couts)


+1 - Breve e al punto. E questo evidenzia il punto principale nella mia risposta che le linee guida del team aiutano a riunire le persone e unificarle in modo che possano lavorare insieme.
jmort253,

Questo commento praticamente risponde alla mia domanda correttamente e porta un argomento solido. Grazie.
Bugster,

1
@ThePlan grazie. tutti hanno avuto ottime risposte a questa domanda.
jglouie,

1
Nota: l'utilizzo printfcoerente funzionerà altrettanto bene dell'uso coutcoerente. Gli unici problemi sono mescolarli insieme e stile.
user253751

Puoi fare un esempio di una funzione in C che non ha un equivalente C ++?
Klut,

20

In generale, C e C ++ vengono considerati come se fossero due lingue completamente separate. Pertanto, può essere considerato una forma errata utilizzare la sintassi C in un programma C ++.

Hai ragione; tuttavia, quel codice C verrà compilato correttamente. Dipende molto dalla flessibilità della tua azienda in termini di standard seguenti. Se mi venisse mai posta la domanda in un'intervista, sarei sicuro di far sapere all'intervistatore che C funziona in C ++, ma anche che C e C ++ sono due lingue separate e probabilmente non dovrebbero essere mescolate a meno che non ci sia un buona ragione per farlo.

Un'altra cosa da considerare è che gli standard aiutano a creare una piattaforma in cui più persone possono facilmente lavorare con il codice. Mentre sei stato fortunato ad avere un insegnante che ti ha incoraggiato ad imparare la C, non tutti possono essere così fortunati. Pertanto, mescolare C in un programma C ++ potrebbe essere fonte di confusione per qualcuno che non aveva mai imparato C.

In sintesi, solo perché puoi fare qualcosa non significa che dovresti, e solo perché non dovresti fare qualcosa non significa che non puoi :)


Vedo. Che dire della funzionalità, ci sono casi particolari in cui la sintassi C è migliore della sintassi C ++?
Bugster,

10

C ++ è retrocompatibile con C in base alla progettazione, quindi di solito il codice C viene compilato dal compilatore C ++ bene (di solito perché ci sono parole riservate aggiuntive in C ++ che non sono in C e potrebbero essere utilizzate nel codice C che interrompe la compilazione).

Tuttavia, lo vedo come una cattiva pratica nel mescolare il codice. Se usi scanf- usa printf, se stai usando operator >>- usa operator <<. Il motivo è che gli operatori C ++ sovraccaricati potrebbero incapsulare funzionalità di cui non si è a conoscenza e la mancata corrispondenza di questi farà sì che il programma esegua operazioni che non si desidera vengano eseguite.

Non vi è alcun motivo particolare per preferire la sintassi C nel codice C ++, questi sono linguaggi diversi e quando si utilizza la sintassi C nel codice C ++, si sta ancora scrivendo codice C ++ , ma non si utilizzano molti dei suoi potenti strumenti.


5
L'incompatibilità tra C e C ++ è più che semplici parole chiave. Il sistema di digitazione cambia e ci sono caratteristiche che esistono in C (specialmente C99), che non esistono in C ++. (Ad esempio, array di lunghezza variabile).
Arafangion,

9

Se mettiamo da parte lo stile di codifica e problemi estetici, ci sono anche vari problemi tecnici che affronti quando usi C nel codice C ++:

  • Che cos'è C? C90, C99 o C11? Potrebbero esserci vari problemi di compatibilità a seconda dello standard C che si sta utilizzando. Tipo booleano, // commenti, funzionalità C99 come VLA, inizializzatori designati ecc.

  • C ++ ha una digitazione più rigorosa di C. Per compilare il codice C in C ++, è molto probabile che sia necessario aggiungere vari tipi di caratteri per ottenere il tipo previsto. Ciò significa che potrebbe essere necessario riscrivere perfettamente il codice C di qualità di produzione per farlo funzionare in C ++.

  • I dattiloscritti applicati da una digitazione più rigorosa sono generalmente solo una buona cosa, ma in alcuni casi possono introdurre o nascondere bug. Prendi il famigerato cast del risultato da malloc () come esempio. Questo dovrebbe essere tipizzato in C ++, ma mai in C. (1)

  • La miscelazione delle funzionalità C e C ++ può portare a bug e comportamenti indefiniti. Ad esempio, non funzionerà per allocare con malloc () e liberarsi con delete . (2)

  • Problemi di sicurezza del thread. La libreria standard C non è thread-safe. La libreria C ++ standard può o meno essere thread-safe, se lo è, quindi l'aggiunta di chiamate alla funzione C library al codice lo distruggerà.

    Come sidenote per programmatori di Windows: il compilatore di Visual C ++ ha avuto un bug di perdita per un bel po 'di tempo, quando la funzione CreateThread () dell'API di Windows è stata utilizzata nello stesso programma della libreria C. (3, 4)

  • La chiamata alla convenzione potrebbe essere un problema per alcuni compilatori, costringendone uno a extern "C"dire esplicitamente quali funzioni dovrebbero essere collegate alla "convenzione di chiamata C".

  • Dettagli fastidiosi. L'operatore virgola si comporta diversamente. La virgola finale nelle dichiarazioni struct / enum è consentita in C99 / C11 ma non in C ++. L'ambito di vari tipi di variabili e funzioni viene trattato in modo diverso. Ecc. Ecc.

Probabilmente ci sono ancora più casi.


Riferimenti:

  1. http://c-faq.com/malloc/cast.html
  2. http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.3
  3. http://www.flounder.com/badprogram.htm#CreateThread
  4. http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx

7

Il motivo per cui C ++ può compilare C è solo per "compatibilità con le versioni precedenti" (evitare di riscrivere il codice di lavoro esistente).

Ma C ++ ha una filosofia diversa rispetto a c. Mischiarli non fa un buon servizio a entrambi.

Il modo in cui C e C ++ gestiscono gli I / O può fare affidamento su un modo diverso di gestire lo stato interno degli I / o. Quindi, almeno, usa costantemente input e output.

E nei programmi C ++ rispetta lo stile C ++ (a meno che non sia richiesto specificatamente altrove)


5

Direi che imparare prima C è, IMHO, una buona idea. In questo modo le persone iniziano a capire l'hardware per cui scrivono il software.

Mescolare queste due lingue non è tuttavia una buona idea. Perché ottieni la folle complessità del C ++ accoppiata a un bit grezzo che gioca in comune con C.

Come puoi vedere, anche in un semplice esempio come il tuo, c'è un problema di sincronizzazione con diversi tipi di flussi e buffering interno. Inoltre, l'approccio C & C ++ non è più flessibile in alcun modo. Passa alla classe x e non ci sono operatori per usare streaming e cose.

È complicato...

Penso davvero che il buon programmatore di C ++ dovrebbe sapere come i bit sono capovolti dietro ogni costrutto e quali sono i comportamenti nascosti.

Ma l'apprendimento del C ++, almeno più del 50% di esso, richiede oltre 5 anni di programmazione professionale e non è possibile gestirlo nel curriculum che dura 6 mesi con circa 20 ore di esperienza pratica.

Se usassi i costrutti C ++ in C, non userei i flussi, sono semplici per la vista a volo d'uccello, e faccio credere alle persone che lo sviluppo del software sia facile, ma nascondono complessità extra senza molti benefici in molte situazioni.

Classi wrapper RAII, modelli, sovraccarichi, correttezza const e classi astratte pure per interfacce comuni (non usare il modo f-ng Java qui PER FAVORE!) Sono buoni candidati però. Perché aggiungono sicurezza, generalità e facilità d'uso che sono molto importanti per i progetti della vita reale. Assicurati di ricordare cose come la distruzione virtuale, la natura esplosiva della costruzione di copie predefinite, il sovraccarico di runtime, la correttezza costante ecc.

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.