Er zijn vijf verschillende manieren om variabelen te gieten. Er is overlapping tussen hen, vooral met de gegoten c-Stijl en alle andere gietvormen, maar elk heeft zijn gebruik. Het is goed om ze allemaal te leren, dus je kunt de beste cast gebruiken voor je specifieke behoefte in plaats van elke cast te gebruiken die toevallig werkt. Als je ooit een snelle referentie nodig hebt, raad ik dit bericht aan StackOverflow.
Ik praat hier niet over impliciet gieten om de eenvoudige reden dat het een basisconcept is met een bijna oneindig aantal variaties. Als ik schrijf zweven f = 10;
Ik heb impliciet een geheel getal naar een float gegooid en het resultaat in f opgeslagen. U kunt ook een object van type B impliciet naar een aanwijzer verwijzen naar zijn basisklasse A met behulp van de operator address of naar een verwijzing naar zijn basisklasse A door een normale toewijzing uit te voeren.
const_cast
De operator const_cast kan const en volatile toevoegen en verwijderen. Het gebruiken van een van deze kenmerken is prima. Het is zeldzaam dat je dat zou doen, maar als je dat wel doet, kan dat.
De mogelijkheid om const te verwijderen, is iets wat je nooit zou moeten gebruiken in een C ++ -programma, behalve wanneer je een C-taalfunctie moet aanroepen die zich niet houdt aan const-correctheid, maar het object helemaal niet aanpast. Als een functie een const-parameter heeft en de constantie ervan weggooit met behulp van const_cast, breekt de functie het impliciete contract dat de parameter niet wordt gewijzigd. Het is dus aan u als auteur van die functie om ervoor te zorgen dat u het object niet gaat wijzigen; anders zou u const voor de parameter niet moeten gebruiken, omdat u het object gaat modificeren.
Als u ooit const_cast en een andere cast-operator op hetzelfde object wilt gebruiken, gebruikt u const_cast als laatste, omdat het verwijderen van const-ness uit een object onbedoelde wijzigingen kan toestaan als u een volgende cast gebruikt.
static_cast
De operator static_cast is handig voor het casten:
Over het algemeen gebruikt u static_cast wanneer u basistypes naar andere basistypes giet. Normaal gesproken zou static_cast je eerste keuze moeten zijn voor casts, omdat het alle controles kan uitvoeren tijdens compilatie, dus je hebt geen run-time controle toegevoegd om je programma te vertragen.
dynamic_cast
De operator dynamic_cast is handig voor het casten van virtuele overerving. static_cast kan van een afgeleide klasse casten naar een basisklasse, ongeacht of de overerving virtueel is of niet. Stel dat je een object van type A krijgt, maar je weet dat het eigenlijk een object van type B is en dat B virtueel van A erft. Als je dit object terug naar B wilt casten om lidfuncties te gebruiken die alleen B biedt, moet je dynamic_cast gebruiken.
Een paar dingen over dynamic_cast. Ten eerste werkt het alleen op pointer-naar-pointer of referentie-naar-referentie-conversies. Ten tweede kan het feitelijk geen object van een A naar een B werpen als het object in feite geen B is (of van een type afgeleid van B). Een pointer-naar-aanwijzer dynamic_cast die mislukt, retourneert nul. Een referentie-naar-referentie fout gooit a std :: bad_cast
uitzondering.
reinterpret_cast
De operator reinterpret_cast is een directe conversie met zeer weinig goede gebruiken. De meeste bewerkingen geven ongedefinieerde resultaten. Wat dit in de praktijk betekent, is dat u de documentatie van de compilerleverancier moet lezen voordat u deze ergens voor gebruikt.
Eén gebruik ervoor, zoals we in zagen StorageDurationSample
, is om een aanwijzer naar een integer type te plaatsen dat groot genoeg is om het vast te houden. Dit geeft het geheugenadres van de aanwijzer, wat handig kan zijn voor foutopsporings- en traceringsoperaties waarbij u gegevens naar logboekbestanden kunt dumpen en kerndumps kunt maken, maar het is mogelijk dat u een foutopsporingsprogramma niet eenvoudig kunt uitvoeren. Je zult zien dat het soms legitiem wordt gebruikt voor andere doeleinden, maar in het algemeen moet het worden beschouwd als de cast van laatste redmiddel (met uitzondering van een cast in C-stijl, die komt na reinterpret_cast).
De cast in C-stijl (bijv., auto someData = (SomeType) dataOfSomeOtherType;
) is niet je vriend. U bent er ongetwijfeld bekend van C #, waar het zeer nuttig is. Als u in C # een cast probeert te maken met die syntaxis en de cast ongeldig is, maakt u een InvalidCastException. Dit gebeurt omdat de CLR bijhoudt welke typen alles u hebt gemaakt en slechte afgietsels detecteert.
C ++ controleert niet of je cast in C-stijl geldig is, ervan uitgaande dat het compileert, natuurlijk. C ++ gaat er gewoon van uit dat het dat is. Als het een slechte cast is, en je hebt geluk, zal je programma onmiddellijk crashen. Als dat niet het geval is, krijg je gegevens in een onbekende staat, die op subtiele en verraderlijke manieren zeker beschadigd raken.
Verder, in tegenstelling tot de andere casts, die je gemakkelijk kunt herkennen door naar _cast te zoeken<, 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.
Het enige dat een cast in C-stijl kan doen, is dat andere casts niet een object kunnen casten naar een van zijn beschermde of private overervingsbasisklassen. U zou dit echt niet moeten doen, want als u openbare overerving nodig heeft, moet u openbaar erfgoed gebruiken.
Kortom, gebruik geen casts in C-stijl.
Er is een voorbeeld, CastingSample, dat de vele mogelijke soorten casting laat zien. Het is opgenomen in de broncode voor deze serie. In het belang van de bondigheid laat ik het hier achterwege.
In dit artikel hebben we het casten in C ++ besproken en ik hoop dat het duidelijk is dat je casts in C-stijl niet moet gebruiken. Het volgende artikel zoomt in op tekenreeksen in C++.
Deze les staat voor een hoofdstuk uit C ++ Kort gezegd, een gratis eBoek van het team van Syncfusion.