C ++ Succinctly Casting i C ++

Oversikt

Det er fem forskjellige måter å støpe variabler på. Det er overlapp mellom dem, spesielt med C-stilkasting og alle andre kaster, men hver har sin bruk. Det er godt å lære dem alle, så du kan bruke den beste støpt for ditt spesifikke behov, i stedet for å bruke noen støp som skjer med jobben. Hvis du noen gang trenger en rask referanse, anbefaler jeg dette innlegget på Stackoverflow.

Jeg diskuterer ikke implisitt avstøpning her av den enkle grunn at det er et grunnleggende konsept med et nesten uendelig antall variasjoner. Hvis jeg skriver flyte f = 10; Jeg har implisitt kastet et heltall til en float og lagret resultatet i f. Du kan også implisitt kaste et objekt av type B til en peker til sin baseklasse A ved hjelp av adressen til operatøren eller til en referanse til sin grunnklasse A ved å gjøre en vanlig oppgave.

const_cast

Const_cast-operatøren kan legge til og fjerne const og flyktig. Å bruke det til å legge til noen av disse attributter, er greit. Det er sjeldent at du ville, men hvis du gjør det, kan du.

Dens evne til å fjerne const er noe du aldri bør bruke i et C ++ -program, bortsett fra når du trenger å ringe en C-språkfunksjon som ikke overholder const-correctness, men endrer ikke objektet i det hele tatt. Hvis en funksjon har en const-parameter, og kaster ut dens constans ved å bruke const_cast, bryter funksjonen den underforståtte kontrakten om at den ikke vil endre parameteren. Så det er opp til deg som forfatter av den funksjonen for å sikre at du ikke kommer til å endre objektet; ellers bør du ikke bruke const for parameteren siden du vil endre objektet.

Hvis du noen gang trenger å bruke const_cast og en annen cast-operatør på samme objekt, bruk const_cast sist, siden fjerning av konstant fra en gjenstand kan føre til utilsiktede endringer som finner sted hvis du brukte en etterfølgende cast.

static_cast

Den static_cast operatøren er nyttig for casting:

  • Flytende punkttyper til heltalltyper (produserer et avkortet resultat)
  • Heltalltyper til flytende punkttyper.
  • Enumtyper til heltalltyper.
  • Heltalltyper til enum typer.
  • Avlede klasser til grunnklasser.
  • En type til en avledet type referanse.
  • En avledet klassepeker til en baseklassepeker.

Generelt, når du støtter grunnleggende typer til andre grunnleggende typer, bruk static_cast. Vanligvis bør static_cast være ditt første valg av gjengivelser, da det gjør alt det som kan gjøres på kompileringstid, slik at du ikke har lagt til kjøretidskontroll for å redusere programmet ditt.

dynamic_cast

Operatoren dynamic_cast er nyttig for casting gjennom virtuell arv. static_cast kan kaste fra en avledet klasse til en grunnklasse, om arven er virtuell eller ikke. Si imidlertid at du får et objekt av type A, men du vet at det egentlig er et objekt av type B - og at B arver nesten fra A. Hvis du vil kaste dette objektet tilbake til B for å bruke medlemsfunksjoner som bare B gir, du må bruke dynamic_cast.

Et par ting om dynamic_cast. For det første fungerer det bare med peker-til-peker eller referanse-til-referanse konverteringer. For det andre kan det faktisk ikke kaste et objekt fra A til B hvis objektet egentlig ikke er en B (eller av en type som er avledet fra B). En pointer-til-peker dynamic_cast som feiler returnerer null. En referanse til referansefeil kaster a std :: bad_cast unntak.

reinterpret_cast

Operatoren reinterpret_cast er en direkte konvertering med svært få gode bruksområder. De fleste operasjoner gir udefinerte resultater. Hva dette betyr i praksis er at du bør lese kompilatorleverandørens dokumentasjon før du bruker den til noe.

En bruk for det, som vi så i StorageDurationSample, er å kaste en peker til en heltall type som er stor nok til å holde den. Dette gir minnesadressen til pekeren, noe som kan være nyttig for feilsøkings- og sporingstransaksjoner der du kan dumpe data til loggfiler og lage kjernefelt, men det kan ikke være mulig å kjøre en debugger enkelt. Du vil se det brukes til tider legitimt til andre formål, men generelt bør det betraktes som kastet av siste utvei (unntatt en C-style cast, som kommer etter reinterpret_cast).


C-stil Cast

C-stilkasten, (f.eks., auto someData = (SomeType) dataOfSomeOtherType;) er ikke din venn. Du er utvilsomt kjent med den fra C #, hvor den er svært nyttig. I C #, hvis du prøver å lage en gjengivelse ved hjelp av syntaksen, og gjengivelsen er ugyldig, vil du lage en InvalidCastException. Dette skjer fordi CLR holder oversikt over typene av alt du har opprettet og oppdager dårlige gjengivelser.

C + + kontrollerer ikke for å se om C-stil-gjengen din er gyldig, forutsatt at den kompilerer, selvfølgelig. C + + antar bare at det er. Hvis det er en dårlig cast, og du er heldig, vil programmet ditt krasje umiddelbart. Hvis ikke, vil du ende opp med data i en ukjent tilstand, som sikkert vil bli ødelagt på subtile og lumske måter.

Videre, i motsetning til de andre støpene, som du lett kan se ved å se etter _cast<, C-style casts do not stick out. When you're scanning lots of code quickly, parentheses wrapped around text looks as much like a function call as it does a cast operation. You could use a regular expression search for this in Visual Studio 2012: \(.*\)[A-Za-z]. Even so, you are still forgoing all the benefits and protections of the other casts.

Den eneste tingen som C-stil støtter kan gjøre de andre gjengene, kan ikke kastes en gjenstand til en av sine beskyttede eller private arvsklasser. Du burde virkelig ikke gjøre dette siden, hvis du trenger offentlig arv, bør du bruke offentlig arv.

Kort sagt, bruk ikke C-stilkasting.

Prøve

Det er en prøve, CastingSample, som demonstrerer de mange mulige typer støping. Den er inkludert med kildekoden for denne serien. For korthetens interesse unnlater jeg det her.

Konklusjon

I denne artikkelen har vi dekket avstøpning i C ++, og jeg håper det er klart at du ikke bør bruke C-style casts. Neste artikkel zoomer inn på strenger i C++.

Denne leksjonen representerer et kapittel fra C ++ Succinctly, en gratis eBok fra teamet på Syncfusion.