IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Les casts en C++


Sujet :

C++

  1. #1
    Invité
    Invité(e)
    Par défaut Les casts en C++
    Bonjour, c'est encore moi, toujours à poursuivre mon apprentissage en C++...

    Je viens de lire un article et la FAQ C++ sur les casts en C++, j'y ai compris pas mal de chose, utilisation des keywords const_cast (utilisation déconseillé), dynamic_cast avec le downcasting et le cross-casting...

    Mais il y a quelque chose que je ne comprend pas mais qui à mon avis semble hyper-simple... C'est l'utilisation des keywords static_cast et reinterpret_cast. Je vois a peu près quand les utiliser, mais je ne vois absolument pas leurs différences... Si quelqu'un peut m'éclaircir sur le sujet, merci.


  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    Le réinterpret_cast est l'équivalent au cast "C style" tout à fait classique, avec tous les inconvénients que cela entraine.

    En C, tu peux parfaitement envisager un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void foo(void * ptr)
    {
        UnType *t= (UnType*) ptr;
        /*...*/
    }
    C'est un transtypage pour le moins dangereux, car cela revient, tout bonnement, à mentir au compilateur au sujet du type de l'objet manipulé, et il n'y a strictement aucun contrôle de validité du transtypage, et tu peux donc envisager de faire passer une pomme pour... une voiture

    Le static_cast apporte déjà une certaine sécurisation au transtypage dans le sens où tu ne peux trantyper un objet que dans un type faisant partie de la même hiérarchie de classes.

    Cependant, tu n'a aucune vérification quant au fait que le type dynamique de l'objet est bel et bien celui dans lequel tu essaye de le transtyper.

    Enfin, tu as le dynamic_cast, qui vérifie à l'exécution que le type dynamique de l'objet correspond à celui dans lequel tu essaye de transtyper ton objet.

    Ceci dit, il faut savoir que la nécessité d'avoir recours au transtypage, quel qu'il soit, est souvent le signe d'un problème de conception, car il est principalement utilisé pour... le "downcasting" (la récupération d'un type dérivé au départ d'un type de base):

    C'est bien souvent le signe que tu as choisi de gérer ton objet au travers d'un type de base trop "générique" par rapport à l'utilisation que tu veux en faire.

    La programmation générique ou le recours à la technique dite du "double dispatch" te permettent bien souvent d'éviter le recours au transtypage
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Le réinterpret_cast est l'équivalent au cast "C style" tout à fait classique, avec tous les inconvénients que cela entraine.

    C'est un transtypage pour le moins dangereux, car cela revient, tout bonnement, à mentir au compilateur au sujet du type de l'objet manipulé, et il n'y a strictement aucun contrôle de validité du transtypage, et tu peux donc envisager de faire passer une pomme pour... une voiture

    Le static_cast apporte déjà une certaine sécurisation au transtypage dans le sens où tu ne peux trantyper un objet que dans un type faisant partie de la même hiérarchie de classes.
    Dans ce cas pourquoi le code suivant ne pose aucun problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    void* valueVoid;
    long* valueLong = static_cast<long*>(valueVoid);
    C'est là aussi mentir au compilateur non ? On fait passer comme tu dis une pomme pour une voiture

    Je ne comprend vraiment pas l'usage du static_cast ici... Normalement j'aurai vu un reinterpret_cast, mais non.

  4. #4
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    static_cast effectue un transtypage à la C justement.

    reinterpret_cast fait un cast bit à bit. MAIS, selon le standard, la seule utilisation correcte est void* <-> entier ou void*<->T* ssi le resultat n'est pas déférencer.

  5. #5
    Invité
    Invité(e)
    Par défaut
    static_cast effectue un transtypage à la C justement..
    Le réinterpret_cast est l'équivalent au cast "C style" tout à fait classique, avec tous les inconvénients que cela entraine.
    Il faudrait savoir... Je présente un code d'exemple à la conversion type C :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    double a;
    double* b = (double*)a;

  6. #6
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    sauf que transtyper un double en double* est une UB.

    donc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    float x;
    double y = static_cast<double>(x);
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    double* p;
    size_t x = reinterpret_cast<int>(p);
    transtyper autre chose que des pointeurs entre eux ou vers des entiers n'a pas de sens avec reinterpret_cast.

    http://msdn.microsoft.com/en-us/libr...8VS.80%29.aspx

  7. #7
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    static_cast sert à convertir entre des types pour lesquels il existe une conversion (entre encodages de nombres, ou en présence d'opérateurs de conversion). Il est aussi requis pour les passages T* <-> void* -- je me souviens d'un fil du forum C où Jean-Marc ou Emmanuel (je ne sais plus lequel des deux) me disait que sizeof(void*) n'est pas forcément égal à sizeof(T*) -- d'où que reinterpret_cast ne marchera pas.
    Comme la FAQ doit le stipuler, cet opérateur permet de downcaster quand la convertibilité est garantie par construction du programme (-> certitude statique)

    reinterpret_cast permet de dire que, une zone mémoire, on va l'interpréter différemment. Généralement, on ne s'en sert que pour (de/)typer des zones mémoire qui sont dans des buffers de bytes (i.e. des buffers de chars). C'est très utilisé pour échanger des objets typés via sockets ou fichiers. Bref, pour sérializer en binaire.
    Toutefois, on s'en méfie car il ne gère nullement les problèmes d'endianess.

    dynamic_cast, c'est pour les downcasting et cross-casting quand on n'a pas la garantie statique de convertibilité.

    const_cast, c'est pour lever les qualificateurs const et volatile. Attention au cas des données const qui non pas d'existence réelle ou qui sont en ROM, le const-cast permettra peut-être de passer la donnée à une fonction qui n'est pas const-correcte, mais il ne permettra pas d'altérer la donnée qui est immuable de par sa nature (et non de par une sémantique à un instant donné)
    (oui, je sais cela mériterait des développements avec plus d'exemples)

    Enfin les cast-C. Cela dépend. Sur les pointeurs void, et les pointeurs entre types hérités, ils vont correspondre à un static_cast. Sur les autres pointeurs, ils vont faire un reinterpret_cast. (ils peuvent aussi faire le boulot de const_cast)
    Entre objets d'une même hiérarchie, cela peut marcher (-> static_cast comme je le disais juste au dessus) sauf quand on est en présence d'héritage virtuel, ou qu'un des types est juste déclaré et non défini à l'endroit du cast. Dans ces deux cas, cela fera n'importe quoi.
    D'où qu'on les fuit comme la peste en situation d'héritage.

    Pour les autres situations, vu qu'il ne sont pas grepables, ils sont juste déconseillés.

    PS: on peut aussi caster via l'écriture constructeur -> int(42.5) <=> (int) 42.5 <=> static_cast<int>(42.5).
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  8. #8
    Invité
    Invité(e)
    Par défaut
    Merci pour ces précisions Luc Hermitte.
    Sujet Résolu.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. GLSL : les casts
    Par zenux dans le forum OpenGL
    Réponses: 4
    Dernier message: 12/06/2008, 00h35
  2. petite question sur l'héritage et les cast
    Par baedal dans le forum Langage
    Réponses: 3
    Dernier message: 29/02/2008, 00h48
  3. Question sur les casts
    Par nicolas66 dans le forum C++
    Réponses: 3
    Dernier message: 16/03/2006, 19h03
  4. [Début.] Les CAST
    Par Sylvester dans le forum Langage
    Réponses: 13
    Dernier message: 08/07/2005, 22h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo