Quand doit-static_cast, dynamic_cast, const_cast et reinterpret_cast être utilisé?
Quelles sont les utilisations de l':
static_cast
dynamic_cast
const_cast
reinterpret_cast
- De style C cast
(type)value
- Fonction de style de fonte
type(value)
Comment décide-t-on pour utilisation dans des cas spécifiques?
- Peut-être une bonne référence ici:Comment expliquez-vous les différences entre static_cast, reinterpret_cast, const_cast, et dynamic_cast pour un nouveau programmeur C++?.
- Pour quelques exemples concrets de l'utilisation de différents types de conversions, vous pouvez consulter la première réponse sur une question similaire dans cette autre sujet.
- Vous pouvez trouver de bonnes réponses à votre question ci-dessus. Mais je voudrais mettre un point de plus ici, @e.James "Il n'y a rien que ces nouveaux c++ opérateurs de transtypage peut faire et c le style de fonte ne peut pas. Ceux-ci sont ajoutés plus ou moins pour une meilleure lisibilité du code."
Vous devez vous connecter pour publier un commentaire.
static_cast
est le casting d'abord, vous devriez essayer d'utiliser. Il fait des choses comme les conversions implicites entre les types (tels queint
àfloat
, ou un pointeur versvoid*
), et il peut également appeler les fonctions de conversion explicite (ou implicitement). Dans de nombreux cas, en indiquant expressémentstatic_cast
n'est pas nécessaire, mais il est important de noter que laT(something)
syntaxe est équivalente à(T)something
et doit être évitée (plus sur cela plus tard). UnT(something, something_else)
est sûr, cependant, et de la garantie d'appeler le constructeur.static_cast
pouvez également exprimés à travers des hiérarchies d'héritage. Il est inutile lors de la coulée vers le haut (une classe de base), mais lors de la coulée vers le bas, il peut être utilisé tant qu'il n'a pas coulé à traversvirtual
héritage. Il ne fait pas de vérification, cependant, et c'est un comportement indéfini àstatic_cast
en bas de la hiérarchie à un type qui n'est en fait pas le type de l'objet.const_cast
peut être utilisé pour supprimer ou ajouter desconst
à une variable; aucune autre C++ cast est capable de le retirer (même pasreinterpret_cast
). Il est important de noter que la modification d'un anciennementconst
valeur n'est pas définie si la variable d'origine, estconst
; si vous l'utilisez pour prendre laconst
off une référence à quelque chose qui n'était pas déclarée avecconst
, c'est sûr. Cela peut être utile en cas de surcharge des fonctions de membre basée surconst
, par exemple. Il peut également être utilisé pour ajouterconst
à un objet, comme pour appeler une fonction membre de surcharge.const_cast
fonctionne aussi de la même façon survolatile
, même si c'est moins fréquent.dynamic_cast
est exclusivement utilisé pour la manipulation de polymorphisme. Vous pouvez jeter un pointeur ou une référence à tout type polymorphe à tout autre type de classe (un type polymorphe a au moins une fonction virtuelle, déclaré ou hérité). Vous pouvez l'utiliser pour plus que juste de coulée vers le bas, vous pouvez lancer sur le côté ou même d'une autre chaîne. Ledynamic_cast
en quête de l'objet désiré et de le retourner si possible. Si il ne peut pas, il sera de retournullptr
dans le cas d'un pointeur, ou de jeterstd::bad_cast
dans le cas d'une référence.dynamic_cast
a certaines limites, cependant. Il ne fonctionne pas si il y a plusieurs objets de même type dans la hiérarchie d'héritage (la soi-disant "tant redoutée de diamant") et que vous n'utilisez pasvirtual
héritage. Il a également ne peut que passer par le public de l'héritage - il échouera toujours à voyager à traversprotected
ouprivate
héritage. C'est rarement un problème, cependant, que de telles formes d'héritage sont rares.reinterpret_cast
est le plus dangereux de fonte, et doit être utilisé avec beaucoup de parcimonie. Il tourne un type vers un autre — comme la coulée de la valeur d'un pointeur à un autre, ou le stockage d'un pointeur dans unint
, ou toutes autres sortes de choses désagréables. En grande partie, la seule garantie que vous obtenez avecreinterpret_cast
est que, normalement, si vous lancez le résultat en arrière à l'original, vous obtiendrez exactement la même valeur (mais pas si le type intermédiaire est plus petit que le type d'origine). Il y a un certain nombre de conversionsreinterpret_cast
ne peut pas le faire, trop. Il est utilisé principalement pour la particulièrement bizarre conversions et peu de manipulations, comme transformer un flux de données brutes en données réelles, ou le stockage des données dans les bits de poids faible de l'alignement de pointeur.De style C cast et fonction de style de fonte sont des distributions à l'aide
(type)object
outype(object)
, respectivement, et sont fonctionnellement équivalents. Ils sont définis comme le premier de la suivante qui réussit:const_cast
static_cast
(mais en ignorant les restrictions d'accès)static_cast
(voir ci-dessus), puisconst_cast
reinterpret_cast
reinterpret_cast
, puisconst_cast
Il peut donc être utilisé comme un remplacement pour les autres distributions, dans certains cas, mais qui peut être extrêmement dangereux en raison de la capacité de se résumer à une
reinterpret_cast
, et celle-ci devrait être préféré quand une conversion explicite est nécessaire, sauf si vous êtes sûrstatic_cast
va réussir oureinterpret_cast
échouera. Même alors, envisager de le plus, plus explicite option.C-style jette également ignorer de contrôle d'accès lors de l'exécution d'un
static_cast
, ce qui signifie qu'ils ont la capacité d'effectuer une opération qu'aucune autre conversion peut. C'est surtout une bidouille, même si, et dans mon esprit, c'est juste une autre raison pour éviter de style C jette.const_cast
sur un pointeur défini? Dire que j'aistd::string s("hi"); auto p = s.c_str();
etp
estconst char*
. Faitconst_cast<char*>(p) = "hello";
comportement défini?const
(même pasreinterpret_cast
)"... vraiment? Qu'en estreinterpret_cast<int *>(reinterpret_cast<uintptr_t>(static_cast<int const *>(0)))
?reinterpret_cast
est souvent l'arme de choix lorsqu'il s'agit d'une API est un ensemble de données opaques typesdynamic_cast
ne fonctionnent pas correctement sur les objets avec les vtables. En d'autres termes, il doit y avoir au moins une fonction virtuelle dans la classe dérivée, vous êtes un casting pour.Utilisation
dynamic_cast
pour la conversion de pointeurs/références au sein d'une hiérarchie d'héritage.Utilisation
static_cast
pour les conversions de type.Utilisation
reinterpret_cast
pour le faible niveau de la réinterprétation des modèles de bits. Utiliser avec une extrême prudence.Utilisation
const_cast
pour la coulée de loinconst/volatile
. Éviter cela, sauf si vous êtes coincé à l'aide d'un const-API incorrects.(Beaucoup de théorique et conceptuel de l'explication qui a été donnée ci-dessus)
Ci-dessous sont quelques-uns des exemples pratiques lorsque j'ai utilisé static_cast, dynamic_cast, const_cast, reinterpret_cast.
(Aussi renvoie cela pour comprendre l'explication : http://www.cplusplus.com/doc/tutorial/typecasting/)
static_cast :
dynamic_cast :
const_cast :
reinterpret_cast :
static_cast<char*>(&val)
?static_cast
ne fonctionne qu'entre les types avec les conversions définies par l', visible par rapport à l'héritage, ou vers desvoid *
. Pour tout le reste, il y a d'autres distributions.reinterpret cast
à toutchar *
type est autorisé à permettre la lecture de la représentation d'un objet - et l'un des seuls cas où le mot clé est utile, pas une déchirure générateur de mise en œuvre-/comportement indéfini. Mais ce n'est pas considéré comme "normal" de la conversion, de sorte que n'est pas permis par la (en général) très conservateurstatic_cast
.EventData
objet et rien d'autre). Malheureusement, je ne pense pas qu'il y a un moyen pratique de type case vide pointeur de façon significative. Idéalement, l'argument serait fortement typées. Juste quelques observations; pas une critique de la réponse.Il pourrait aider si vous savez peu de internals...
static_cast
static_cast
pour eux.A
àB
,static_cast
appelsB
s'constructeur passantA
comme param. Sinon,A
pourrait avoir un opérateur de conversion (c'est à direA::operator B()
). SiB
n'a pas de telles constructeur, ouA
ne dispose pas d'un opérateur de conversion, puis vous obtenez l'erreur de compilation.A*
àB*
réussit toujours si A et B sont dans la hiérarchie d'héritage (ou nulle), sinon vous obtenez des erreurs lors de la compilation.A&
àB&
.dynamic_cast
(Base*)
à(Derived*)
peut échouer si le pointeur n'est pas réellement de type dérivé.A*
àB*
, si la fonte n'est pas valide alors dynamic_cast sera de retour nullptr.A&
àB&
si le casting n'est pas valide alors dynamic_cast va jeter bad_cast exception.const_cast
set<T>
qui retourne seulement ses éléments comme const pour vous assurer de ne pas changer sa clé. Cependant si votre intention est de modifier l'objet du non-membres clés alors qu'il devrait être ok. Vous pouvez utiliser const_cast pour supprimer constness.T& foo()
ainsi queconst T& foo()
. Pour éviter la duplication de code, vous pouvez appliquer const_cast à la valeur de retour d'une fonction à partir d'un autre.reinterpret_cast
const_cast
est incorrect: seulementdynamic_cast
a effectivement la gestion d'exécution. Il semble que vous peut avoir passé la commande et j'ai oublié de déplacer et de modifier le libellé de celui-là.If you cast base pointer to derived pointer but if actual object is not really derived type then you don't get error. You get bad pointer and segfault at runtime.
Vous obtenez UB qui peut entraîner une erreur de segmentation lors de l'exécution si vous avez de la chance. 2. Dynamique moulages peuvent également être utilisés dans des casting. 3. Const moulages peuvent entraîner UB dans certains cas. À l'aide demutable
peut être un meilleur choix pour mettre en œuvre des logiques constness.mutable
, de la croix de la coulée, etc.Ne cette répondre à votre question?
Je n'ai jamais utilisé
reinterpret_cast
, et me demande si en cours d'exécution dans un cas, il n'est pas une odeur de mauvaise conception. Dans la base de code, je travaille surdynamic_cast
est beaucoup utilisé. La différence avecstatic_cast
est qu'undynamic_cast
ne contrôle d'exécution qui peut (safer) ou ne peuvent pas (plus les frais généraux) être ce que vous voulez (voir msdn).reinterpret_cast
pour extraire des éléments de données d'un tableau. Par exemple si j'ai unchar*
contenant un gros tampon plein de paniers de données binaires que j'ai besoin de se déplacer à travers et obtenir les primitives de différents types. Quelque chose comme ceci:template<class ValType> unsigned int readValFromAddress(char* addr, ValType& val) { /*On platforms other than x86(_64) this could do unaligned reads, which could be bad*/ val = (*(reinterpret_cast<ValType*>(addr))); return sizeof(ValType); }
reinterpret_cast
, il n'y a pas de très nombreuses utilisations.En plus des autres réponses, ici, c'est pas évident exemple où
static_cast
n'est pas suffisante pour quereinterpret_cast
est nécessaire. Supposons qu'il existe une fonction qui à un paramètre de sortie renvoie des pointeurs vers des objets de classes différentes (qui ne partagent pas une classe de base commune). Un exemple réel de ce genre de fonction estCoCreateInstance()
(voir le dernier paramètre, qui est en faitvoid**
). Supposons que vous demande en particulier de la classe de l'objet à partir de cette fonction, de sorte que vous savez à l'avance le type du pointeur (qui on fait souvent pour les objets COM). Dans ce cas, vous ne peut pas lancer de pointeur vers le pointeur de la souris dansvoid**
avecstatic_cast
: vous avez besoin dereinterpret_cast<void**>(&yourPointer)
.Dans le code:
Cependant,
static_cast
travaille pour de simples pointeurs (pas de pointeurs de pointeurs), le code ci-dessus peut être réécrite de façon à éviterreinterpret_cast
(au prix d'une variable supplémentaire) de la façon suivante:Tandis que d'autres réponses joliment décrit toutes les différences entre le C++ jette, je voudrais ajouter une courte note pourquoi vous ne devriez pas utiliser le C-style jette
(Type) var
etType(var)
.Pour C++ débutants C-style jette ressemble en apparence le sur-ensemble de l'opération sur C++ jette (static_cast<>(), dynamic_cast<>(), const_cast<>(), reinterpret_cast<>()) et si quelqu'un pourrait préférez sur le C++ jette. En fait de style C cast est le sur-ensemble et de la plus courte à écrire.
Le principal problème de C-style jette, c'est qu'ils cachent développeur intention réelle de la fonte. Le style C moulages peuvent faire pratiquement tous les types de moulage de normalement sans danger jette fait par static_cast<>() et dynamic_cast<>() pour potentiellement dangereux jette comme const_cast<>(), où const modificateur peut être retiré afin const variables peuvent être modifiées et reinterpret_cast<>() qui permet même de réinterpréter les valeurs entières de pointeurs.
Voici l'échantillon.
La raison principale pourquoi C++ fontes ont été ajoutés à la langue était de permettre à un développeur de clarifier ses intentions, pourquoi il va le faire en fonte. À l'aide de C-style de moulages qui sont parfaitement valide en C++, vous faites de votre code moins lisible et plus enclins à faire des erreurs, surtout pour les autres développeurs qui n'ont pas de créer votre code. Afin de rendre votre code plus lisible et explicite, vous devez toujours préférer C++ jette sur C-style jette.
Ici est une courte citation de Bjarne Stroustrup (l'auteur de C++) du livre Le Langage de Programmation C++ 4e édition - page 302.
Pour comprendre, prenons l'exemple de code ci-dessous extrait de:
Seule ligne (4) compile sans erreur. Seulement reinterpret_cast peut être utilisé pour convertir un pointeur vers un objet à un pointeur vers un tout autre type d'objet.
Un ce, il convient de souligner: La dynamic_cast serait un échec au moment de l'exécution, cependant, sur la plupart des compilateurs elle échoue également à compiler, car il n'y a pas de fonctions virtuelles dans la structure du pointeur d'être coulé, sens dynamic_cast fonctionnera avec seulement polymorphes pointeurs de la classe.
Lors de l'utilisation de C++ cast: