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 :

[Transtypage] encore une erreur static_cast


Sujet :

C++

  1. #1
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut [Transtypage] encore une erreur static_cast
    Je ne comprends pas l'usage de static_cast. Pourquoi un code aussi simple que celui-ci est refusé ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		int *pi=new int(25);
    		long *pl=static_cast<long *>(pi);
    Convertir un pointeur en un autre pointeur, quel qu'il soit, devrait être accepté par static_cast, c'est bien son but quand même ?

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ben non, caster des pointeurs de types sans relation, c'est le rôle du reinterpret_cast.
    Static_cast peut caster un entier en long, par contre.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Convertir un pointeur en un autre pointeur, quel qu'il soit, devrait être accepté par static_cast, c'est bien son but quand même ?
    Il n'y a *aucun* cast qui permette ceci, même le cast C-style (le plus permissif) ne le permet pas.

    Les casts C++ existent pour ne permettre que très peu de choses et ainsi éviter les erreurs.

    C-style cast : conversion entre deux pointeurs vers des objets, conversion entre deux pointeurs vers des fonctions, conversion entre pointeur et entier, conversion entre différents types d'entiers et de flottants.
    reinterpret_cast : même chose que le C-style cast, sauf que const et volatile ne peuvent pas être modifiés pour les conversions entre pointeurs vers des objets.
    const_cast : conversion entre deux pointeurs vers des objets dont seuls les qualifiants const et volatile peuvent varier.
    static_cast : conversion entre différents types d'entiers et de flottants, et conversion entre différents pointeurs vers des objets si le type cible est dérivé ou si l'entrée est void*. Ne peut bien sûr pas modifier const et volatile.

    Après il y a aussi les conversions explicites et implicites, qui sont à utiliser de préférence si elles suffisent.
    Le C-style cast est à éviter, au moins pour les casts entre pointeurs vers des objets.
    Boost ftw

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Euh... Qu'est-ce que le C-Style cast ne parmet pas, à part les casts entre pointeurs de fonction et pointeurs vers n'importe quoi d'autre?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Si j'ai bien compris, ceci est un classement du plus permissif au moins permissif:
    C-style
    reinterpret_cast
    static_cast
    const_cast

    J'utilise souvent le C-style. Je voulais justement me défaire de mes habitudes C, ainsi reinterpret_cast est "l'équivalent" C++ du C-style et non pas static_cast comme je le croyais.
    Merci.

  6. #6
    screetch
    Invité(e)
    Par défaut
    le C-cast n'est pas equivalent au reinterpret_cast, il y a de subtiles différences...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #include <cstdio>
     
    class A;
    class B;
    class C;
     
    class A
    {
    	int offset;
    };
     
    class Aprime
    {
    	int offset2;
    };
     
    class B : public Aprime, public A
    {
    	int value;
    };
     
    static void testB(A* a)
    {
    	B* b1 = (B*)a;
    	B* b2 = reinterpret_cast<B*>(a);
    	B* b3 = static_cast<B*>(a);
    	printf("a : %p\nC-cast : %p\nreinterpret_cast : %p\nstatic_cast : %p\n", a, b1, b2, b3);
    }
     
    static void testC(A* a)
    {
    	C* c1 = (C*)a;
    	C* c2 = reinterpret_cast<C*>(a);
    	printf("a : %p\nC-cast : %p\nreinterpret_cast : %p\nstatic_cast : unavailable\n", a, c1, c2);
    }
     
    class C : public Aprime, public A
    {
    	int value;
    };
     
    int main()
    {
    	A* b = new B;
    	A* c = new C;
     
    	testB(b);
    	testC(c);
    }
    ici, il y a double heritage, un B est donc un A et un Aprime
    Aprime etant le premier

    les données d'un B sont donc celles d'un A et d'un Aprime
    dans l'ordre, on a les données de Aprime puis celle de A
    donc, si on veut considérer un B comme un Aprime, il suffit de mettre le pointeur sur les données de Aprime
    si on veut considérer un B comme un A, il faut mettre le pointeur sur les données de A (qui sont apres Aprime)

    donc, un cast de B en A devrait renvoyer un pointeur sur les données de A qui sont a l'interieur de B, pas sur le debut de B (j'espere me faire bien comprendre)
    c'est l'opération correcte a faire.

    Ici, ce programme donne le résultat des differents cast :
    - un reinterpret_cast ne fera jamais cette operation, il va changer un pointeur sur B en un pointeur sur A, mais en fait ce pointeur pointera sur Aprime. Il a fait ce qu'on lui a demandé, REINTERPRETER le pointeur en autre chose
    - un static_cast fera la bonne opération lui, a condition de savoir comment faire un pointeur sur B a partir d'un pointeur sur A, c'est a dire avoir la définition des classes B et A et Aprime. Le static_cast echouera pour C car il ne sait pas comment faire un pointeur sur C a partir d'un pointeur sur A.
    - Le C-cast va marcher des fois, et des fois pas; des fois il va faire comme reinterpret_cast et des fois comme static_cast
    Lorsque le c-cast connait la définition des classes, il fait la bonne opération
    lorsqu'il ne connait pas (dans le cas du C plus haut, il ne voit pas la definition de C) alors un c-cast fera comme un reinterpret_cast.


    C-cast c'est la mort lente du développeur. Utilisez static_cast, evitez reinterpret_cast.

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Le C-style cast n'est pas un équivalent du reinterpret_cast<>. Sans aller jusqu'au subtilités soulignées par screetch, il correspond plus à un reinterpret_cast<> plus un const_cast<>. Cela le rend extrêmement dangereux, à bannir dès que des pointeurs const sont en jeu.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    screetch
    Invité(e)
    Par défaut
    a bannir pour tous les pointeurs a priori, const ou non const =)

    a garder pour changer un int en un float, a la rigueur... mais un bon veux checked_numcast<>() fait aussi beaucoup mieux

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    #include <cassert>
    template< typename R, typename T >
    R checked_numcast(T value)
    {
    	R r = (R)value;
    #ifdef _DEBUG
    	assert((T)r == value);
    #endif
    	return r;
    }
     
    int main()
    {
    	float i = 1.0f;
    	int i2 = checked_numcast<int>(i);
    	i = 1.2f;
    	i2 = checked_numcast<int>(i);
    }

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    À quoi sert exactement ton #if ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Je pense que pour ce que je veux, je dois utiliser reinterpret_cast, c'est-à-dire que la valeur du pointeur reste identique quelque soit le cast (donc la zone mémoire pointée):
    char *cp=new char[1000];
    void *vp=cp;
    UneStructure *sp=reinterpret_cast<UneStructure>(vp);
    UneClasse *lp=reinterpret_cast<UneClasse>(sp);

    Quant au C-style, si le résultat est vraiment du genre une-fois-je-static-une-fois-je-reinterpert, c'est plutôt dangeureux. Heureusement que je ne m'aventure que rarement (jamais ?) dans l'héritage multiple.

  11. #11
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    À quoi sert exactement ton #if ?
    a plus rien, je voulais le mettre pour avoir une fonction d'erreur personnalisée pis j'ai été attaqué par cette fourberie qu'on appelle la flemme, alors j'ai mis assert a la place. pis, toujours sous le coup de la flemme, j'ai pas retiré le #if. vala.

  12. #12
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par camboui Voir le message
    Je pense que pour ce que je veux, je dois utiliser reinterpret_cast, c'est-à-dire que la valeur du pointeur reste identique quelque soit le cast (donc la zone mémoire pointée):
    char *cp=new char[1000];
    void *vp=cp;
    UneStructure *sp=reinterpret_cast<UneStructure>(vp);
    UneClasse *lp=reinterpret_cast<UneClasse>(sp);

    Quant au C-style, si le résultat est vraiment du genre une-fois-je-static-une-fois-je-reinterpert, c'est plutôt dangeureux. Heureusement que je ne m'aventure que rarement (jamais ?) dans l'héritage multiple.
    oui, c'est ca, c'est un reinterpret_cast cela.

  13. #13
    Membre actif Avatar de g0up1l
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 341
    Points : 294
    Points
    294
    Par défaut
    juste pour info : à noter le qui te permet de savoir si ton transtypage s'est bien passé ou non.
    Hope it helps !
    Nouveau ! Il y a une vie après le java, oxygénez-vous

  14. #14
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Ok, merci.
    On va dire que c'est résolu

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

Discussions similaires

  1. Encore une erreur sql
    Par Paulinio86 dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 17/06/2015, 14h24
  2. Encore une erreur de da.Update(ds, "blabla")
    Par Biggy30 dans le forum Accès aux données
    Réponses: 1
    Dernier message: 01/04/2014, 23h57
  3. [MySQL] (Encore une) Erreur de syntaxe MySQL
    Par n1n0x dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 14/04/2008, 18h30
  4. Encore une erreur de compilation
    Par MarioNoFearS dans le forum C++
    Réponses: 3
    Dernier message: 02/06/2007, 13h05
  5. [Tableaux] encore une erreur du au changement
    Par cyrill.gremaud dans le forum Langage
    Réponses: 17
    Dernier message: 15/06/2006, 09h47

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