2801 votes

Quand devraient utiliser static_cast, dynamic_cast, const_cast et reinterpret_cast ?

Quels sont les usages appropriés de :

  • ``
  • ``
  • ``
  • ``
  • Cast de style C``
  • Cast de style fonction``

et comment on décide celle à utiliser dans un cas concret ?

2812voto

coppro Points 10692

static_cast est le casting d'abord, vous devriez essayer d'utiliser. Il fait des choses comme les conversions implicites entre les types (tels que int, float, ou un pointeur de type void*), et il peut également appeler les fonctions de conversion explicite (ou implicite). Dans de nombreux cas, en indiquant expressément static_cast n'est pas nécessaire, mais il est important de noter que l' T(something) syntaxe est équivalente à (T)something et doit être évitée (plus sur cela plus tard). Un T(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 jeté par virtual d'héritage. Il ne fait pas de vérification, cependant, et c'est un comportement indéfini d' static_cast vers le 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 des const à une variable; aucune autre C++ cast est capable de le retirer (même pas reinterpret_cast). Il est important de noter que la modification d'un anciennement const de la valeur n'est pas définie si la variable d'origine, est const; si vous l'utilisez pour prendre l' const off une référence à quelque chose qui n'était pas déclarée avec const, c'est sûr. Cela peut être utile en cas de surcharge des fonctions de membre basée sur const, par exemple. Il peut également être utilisé pour ajouter de l' const à un objet, comme pour appeler une fonction membre de la surcharge.

const_cast fonctionne aussi de la même façon sur volatile, même si c'est moins fréquent.


dynamic_cast est presque 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. L' dynamic_cast quête de l'objet désiré et de le retourner si possible. Si il ne peut pas, il sera de retour NULL dans le cas d'un pointeur, ou de jeter std::bad_cast dans le cas de référence.

dynamic_cast a certaines limitations. 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 pas virtual d'héritage. Il a également ne peut que passer par le public de l'héritage - il échouera toujours à voyager à travers l' protected ou private d'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 un int, ou toutes autres sortes de choses désagréables. En grande partie, la seule garantie que vous obtenez avec reinterpret_cast , c'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 conversions reinterpret_cast ne peuvent pas 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.


C casts sont des distributions à l'aide de (type)object ou type(object). Un style C cast est définie comme étant 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), alors const_cast
  • reinterpret_cast
  • reinterpret_cast, alors const_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é à déléguer en reinterpret_cast, et celles-ci devraient être privilégiées lors de la conversion explicite est nécessaire, sauf si vous savez static_cast réussira ou reinterpret_cast échouent. Même ensuite, tenir compte de la plus, la plus explicite de l'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.

380voto

Fred Larson Points 27404

Utilisation `` pour convertir les pointeurs et références au sein d’une hiérarchie d’héritage.

Utilisation `` pour les conversions de type ordinaire.

Utilisation `` pour réinterpréter à basse altitude des modèles binaires. Utiliser avec une extrême prudence.

Utilisation pour effectuer le cast away . Pour éviter cela que si vous êtes coincé à l’aide d’une API de const-incorrecte.

223voto

Sumit Arora Points 196

(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/)

statique de la distribution :

OnEventData(void* pData)

{
  ......

  //  pData is a void* pData, 

  //  EventData is a structure e.g. 
  //  typedef struct _EventData {
  //  std::string id;
  //  std:: string remote_id;
  //  } EventData;

  // On Some Situation a void pointer *pData
  // has been static_casted as 
  // EventData* pointer 

  EventData *evtdata = static_cast<EventData*>(pData);
  .....
}

dynamic_cast :

void DebugLog::OnMessage(Message *msg)
{
    // typecasting the message data based on the message type
    switch (msg->message_id)
    {
        case MSG_DEBUG_OUT:
        {
            DebugMsgData *data = dynamic_cast<DebugMsgData*>(msg->pdata);
                }

            case MSG_XYZ:
        {
            XYZMsgData *data = dynamic_cast<XYZMsgData*>(msg->pdata);
             }
         .....
         }
}

const_cast :

// *Passwd declared as a const

const unsigned char *Passwd


// on some situation it require to remove its constness

const_cast<unsigned char*>(Passwd)

reinterpret_cast:

typedef unsigned short uint16;

// Lecture des Octets renvoie que 2 octets ai lu.

bool ByteBuffer::ReadUInt16(uint16& val) {
  return ReadBytes(reinterpret_cast<char*>(&val), 2);
}

17voto

andreas buykx Points 4710

N' cette réponse à votre question?

Je n'ai jamais utilisé reinterpret_cast, et de se demander si dans un cas il n'est pas une odeur de mauvaise conception. Dans la base de code, je travaille sur dynamic_cast est beaucoup utilisé. La différence avec l' static_cast est qu'un dynamic_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).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X