cast di stile c o cast di stile c ++


21

Allora, cosa usi?

int anInt = (int)aFloat;

o

int anInt = static_cast<int>(aFloat);
// and its brethren

E, soprattutto, perché?

Risposte:


45

Innanzitutto, capire che quelle linee non sono equivalenti .

int* anInt = (int*)aFloat; // is equivalent to

int* anInt = reinterpret_cast<int*>(aFloat); 

Quello che sta succedendo qui è che il programmatore sta chiedendo al compilatore di fare tutto il possibile per realizzare il cast.

La differenza è importante perché l'utilizzo di static_cast richiederà solo un tipo di base "sicuro" in cui convertire, dove reinterpret_cast verrà convertito in qualsiasi cosa, possibilmente mappando il layout di memoria desiderato sulla memoria dell'oggetto specificato.

Pertanto, poiché il "filtro" non è lo stesso, l'utilizzo di cast specifici è più chiaro e sicuro rispetto all'utilizzo del cast C, se si fa affidamento sul compilatore (o impl runtime se si utilizza dynamic_cast) per dirti dove hai fatto qualcosa di sbagliato , evitando C cast e reinterepret_cast.

Ora che questo è più chiaro, c'è un'altra cosa: static_cast, reinterpret_cast, const_cast e dynamic_cast sono più facili da cercare .

E l'ultimo punto: sono brutti . Questo è voluto. Codice potenzialmente difettoso, odori di codice, ovvi "trucchi" che potrebbero generare bug, sono più facili da rintracciare quando sono associati a un brutto aspetto. Il codice errato dovrebbe essere brutto .

Questo è "di progettazione". E ciò consente allo sviluppatore di sapere dove avrebbe potuto fare meglio le cose (evitando totalmente i cast, se non proprio necessari) e dove va bene, ma è "documentato" nel codice "contrassegnandolo" come brutto.

Un motivo secondario per introdurre il cast di nuovo stile era che i cast in stile C sono molto difficili da individuare in un programma. Ad esempio, non è possibile cercare comodamente i cast utilizzando un normale editor o elaboratore di testi. Questa quasi invisibilità dei cast in stile C è particolarmente sfortunata perché sono potenzialmente dannosi. Una brutta operazione dovrebbe avere una brutta forma sintattica. Tale osservazione faceva parte del motivo della scelta della sintassi per i cast di nuovo stile. Un ulteriore motivo era che i cast di nuovo stile corrispondessero alla notazione del modello, in modo che i programmatori potessero scrivere i propri cast, in particolare i cast controllati in fase di esecuzione.

Forse, poiché static_cast è così brutto e relativamente difficile da digitare, è più probabile che tu ci pensi due volte prima di usarne uno? Sarebbe positivo, perché i cast sono per lo più evitabili nel C ++ moderno.

Fonte: Bjarne Stroustrup (creatore di C ++)


2
Voterei questo voto se avessi qualche punto in più, ma sfortunatamente non posso. I cast in stile c NON sono equivalenti a reinterpret_cast. Prendere in considerazione reinterpret_cast<int>(double);. È del tutto possibile eseguire il cast di un doppio in un int con un cast in stile c, ma non è possibile farlo con reinterpret_cast. Vedo che Timbo te lo ha già indicato e hai detto che lo avresti risolto, ma quattro anni dopo rimane errato. Vorrei comunque sottoporvi al voto se ciò fosse risolto, poiché ci sono ragioni perfettamente valide per usare un cast. Ecco una risposta migliore: stackoverflow.com/a/332086/3878168
Yay295

36

I cast C ++ sono più restrittivi (quindi esprimi meglio le tue intenzioni e rendi più facile la revisione del codice, ecc.). Sono anche molto più facili da cercare, se mai ne hai bisogno.


10
... e hanno maggiori probabilità di fare ciò che intendi. ;-)
Macke,

7
E sono molto di più da digitare, dandoti un motivo in più per ottenere i tuoi tipi corretti senza il cast necessario.
Michael Kohne,

7
E sono brutti come funzionalità, rendendo evidente dove nel codice potrebbero esserci punti di miglioramento o casi speciali che potrebbero richiedere documentazione. - modifica: wow ho appena scoperto di aver risposto anche a questa domanda! XD
Klaim,

Ora, perché dovrei cercarli?
Deduplicatore,

@Deduplicator Ci sono molte ragioni per cui potresti voler sapere dove avvengono i cast in una base di codice. Ad esempio quando si cacciano bug che potrebbero essere associati al casting (in particolare quando si fa sviluppo multipiattaforma).
Klaim,

13

Opzione C: un cast di tipo "C ++", perché non è distinguibile da una costruzione:

int anInt = int(aFloat);

o anche:

int anInt(aFloat);

A parte questo, a parte questi casi banali con primitivi, che sono ben compresi, preferisco usare x_cast <> s su cast in stile C. Ci sono tre ragioni per cui:

  • Definiscono più strettamente l'operazione che il programmatore stava cercando di eseguire.

  • Possono eseguire azioni che non possono essere lanciate in stile C (specialmente nel caso di dynamic_cast <>, che può eseguire il cast incrociato tra i rami di una catena a ereditarietà multipla).

  • Sono brutti . Dichiarano a gran voce che il programmatore sta lavorando contro il sistema di tipi. In questo caso, è una buona cosa.


7

Se scrivi il codice in C usa un cast C. Se scrivi in ​​C ++ usa un cast C ++.

Mentre la maggior parte dei casting rompe la corretta sicurezza del tipo, quelli in C ++ sono più restrittivi, e quindi sei leggermente meno insicuro rispetto al tipo di un cast in C.

Posso tollerare qualcuno usando (T *) NULL anche se per forzare un sovraccarico ...


7

Ho alcune regole sui cast in stile C / C ++:

  1. Disapplicare una const deve sempre usare a const_cast. Per ovvie ragioni. Sfortunatamente, la mia regola di non applicare una const che fa alzare la tastiera e rompere il dito del programmatore non è stata approvata.
  2. Tutti gli shenanigani in stile manipolazione dei bit che i programmatori si avvicinano quando scendono al metal dovrebbero usare reinterpret_cast. È davvero il tipo di cast che C non ha: fingi che i bit di questo numero intero siano in realtà bit di un float. Questo evita spiacevoli piacere (int)(*(int*)(&floatVar)).
  3. Se si digitano le parole " dynamic_cast", interrompere e rivalutare la gerarchia e il design della classe polimorfica. Continua a rivalutare il design della gerarchia di classi fino a quando non puoi eliminare quelle parole.
  4. Non preoccuparti static_cast.

Il ragionamento dietro # 4 è semplicemente che non importa. Le circostanze che non rientrano nelle altre regole sono ovvie o veramente di basso livello. Una conversione ben comprensibile di tipi semplici come int-to-float non dovrebbe richiedere una sintassi speciale. E se sei nel profondo, brutto fegato di qualcosa, beh, sei nel profondo, brutto fegato di qualcosa. Non c'è bisogno di attirare l'attenzione sul fatto che "qui ci sono draghi", poiché i denti, gli artigli e il fuoco lo hanno praticamente già dato via.


1
dynamic_castè uno strumento perfettamente valido. Raramente utile, lo ammetto, ma è ben lungi dall'essere Satana di cose come le variabili globali. Tuttavia, in primo luogo, ti ho votato a fondo perché non hai risposto alla domanda , che riguardava l'uso o meno dei cast in stile C.
DeadMG

2
@DeadMG: ho parlato di cast in stile C. L'intero ultimo paragrafo giustifica i cast in stile C a favore di static_cast.
Nicol Bolas,

"Purtroppo, la mia regola di non applicare una const che fa alzare la tastiera e rompere il dito del programmatore non è stata approvata." Tecnicamente è in realtà legale per il compilatore farlo accadere. Come è legale per il compilatore far volare i demoni dal tuo naso .
Pharap,


3

Dipende molto dalla lingua con cui sto lavorando, dato che sai cosa dicono: a Roma parla il romano. Quindi, se sto programmando in C, provo ad usare le funzionalità C al massimo, ma se sto programmando in C ++ vado avanti e uso le funzionalità C ++ al massimo, anche se alcune persone non amano questo approccio perché dicono che rende il codice "meno portabile", dico che non mi interessa, sono in C ++ e programmazione in C ++, e ho bisogno di un compilatore completamente compatibile C ++ per compilare il codice, altrimenti lavorerei con qualcosa di diverso innanzitutto.


Non funziona davvero cercando di usare i cast in stile C ++ in C ;-)
Steve314

3

static_cast etc sono stati inventati a causa di problemi con i cast in stile C quando usati nei template. Se stai scrivendo un modello, o se il tuo codice può essere successivamente convertito in un modello, è una buona idea usare cast in stile C ++. Il motivo è perché i cast in stile C ++ esprimono meglio l'intento, quindi daranno i risultati previsti nei casi in cui i cast in stile C faranno la cosa sbagliata (dati i tipi particolari come parametri del modello).

A parte questo, dico di usare i cast in stile C ++ se hai un problema specifico che li necessita - dynamic_cast è il più comune, ma probabilmente non è una cosa di tutti i giorni.

Qualsiasi altra cosa, e un cast in stile C potrebbe essere un po 'meno disordinato e aiutare la leggibilità, o forse non a seconda di quanto il lettore abbia familiarità con quello stile di cast in questi giorni. A mio avviso non è molto importante, soprattutto una preferenza personale, anche se non sorprenderti se alcune persone non apprezzano lo stile C.

Nota finale: se hai bisogno di così tanti cast che questo è un grosso problema, probabilmente stai facendo qualcos'altro di sbagliato. Ci sono eccezioni a ciò in alcuni casi, ma la maggior parte del codice di alto livello non dovrebbe aver bisogno di molti cast (se presenti).

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.