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 :

Conversion d'un void *objet


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    38
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 38
    Par défaut Conversion d'un void *objet
    Bonjour,

    Pour un appel callback dans un trackbar d'opencv, ça fait 3 jours que j'essaie de convertir un objet void *adresse en un objet Myclass myobjet_dst, étant entendu que le *adresse pointe vers un objet de type Myclass myobjet_src.

    J'ai essayé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void ontrack(int param, void *adresse)		
    {
     
             Myclass *myobjet_dst = static_cast<Myclass*>(adresse);
    ...}

    ou encore

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void ontrack(int param, void *adresse)		
    {
            Myclass& myobjet_dst = (Myclass&)(adresse)
    ...}

    et j'en passe.
    Faut-il créer un constructeur particulier pour Myclass, qui prendrait une adresse en paramètre d'entrée ?

    Je sèche sur ce problème.

    Merci par avance pour votre aide.

  2. #2
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 033
    Billets dans le blog
    12
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Myclass *myobjet_dst = reinterpret_cast<Myclass*>(adresse);
    static_cast est pour les objets ayant une relation d'héritage entre eux, ou pour les types ayant défini des conversions implicites de la source à la cible.
    reinterpret_cast est pour "forcer" le cast d'un type à un autre (avec certaines règles, cependant, cf. la doc), déconseillé si on ne sait pas ce qu'on fait.
    Je ne parlerai pas du troisième qui n'a aucune utilité bien fondée
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  3. #3
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    38
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 38
    Par défaut
    merci beaucoup pour ton aide et ta réponse plus que rapide.

  4. #4
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    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 296
    Par défaut
    static_cast est bien le cast officiel pour gérer les conversion depuis void* (probablement parce qu'il n'y a pas de garantie que sizeof(void*) == sizeof(T*)). Corrigé avec le C++11 on dirait.

    Le reinterpret_cast a vraiment corrigé le problème ? Je serai plutôt parti sur la piste d'un problème à l'appel.
    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...

  5. #5
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Myclass& myobjet_dst = *((Myclass*)(adresse))

  6. #6
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    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 296
    Par défaut
    Ne JA-MAIS faire de casts à la C en C++. Surtout quand des classes sont impliquées. Les chances pour que cela parte en cacahuète sont trop importantes. Un code qui marche peut planter après un refactoring. Donc oublis!

    Au mieux ici si tu veux une référence.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void ontrack(int param, void *adresse)		
    {
        assert(addresse);
        Myclass & myobjet_dst = *static_cast<Myclass*>(adresse);
    }
    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...

  7. #7
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Citation Envoyé par crazyfroggy Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void ontrack(int param, void *adresse)		
    {
     
             Myclass *myobjet_dst = static_cast<Myclass*>(adresse);
    }
    Pourtant, dans la doc de static_cast, on peut lire :
    10) A prvalue of type pointer to void (possibly cv-qualified) can be converted to pointer to any type. If the value of the original pointer satisfies the alignment requirement of the target type, then the resulting pointer value is unchanged, otherwise it is unspecified. Conversion of any pointer to pointer to void and back to pointer to the original (or more cv-qualified) type preserves its original value.
    [...]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // 10. void* to any type
    void* voidp = &e;
    std::vector<int>* p = static_cast<std::vector<int>*>(voidp);
    Chez moi, le code suivant compile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct Foo {};
    void bar(void* adresse)		
    {
    	Foo* ptr = static_cast<Foo*>(adresse);
    }
    Citation Envoyé par Astraya Voir le message
    Regarder tous les codes type Unreal Engine 4 et autre qui ne veulent pas du RTTI, on cast à la C. Drivers on cast à la C, performance on cast à la C.
    En C++, le cast avec la syntaxe du C n'est pas plus performant !
    C'est seulement :
    • soit une combinaison implicite de const_cast, de static_cast et de reinterpret_cast,
    • soit une conversion que ne permettent pas les xxxxx_cast ci-dessus.

    Documentation :
    When the C-style cast expression is encountered, the compiler attempts to interpret it as the following cast expressions, in this order:
    a) const_cast<new_type>(expression);
    b) static_cast<new_type>(expression), with extensions: pointer or reference to a derived class is additionally allowed to be cast to pointer or reference to unambiguous base class (and vice versa) even if the base class is inaccessible (that is, this cast ignores the private inheritance specifier). Same applies to casting pointer to member to pointer to member of unambigous non-virtual base;
    c) static_cast (with extensions) followed by const_cast;
    d) reinterpret_cast<new_type>(expression);
    e) reinterpret_cast followed by const_cast.
    The first choice that satisfies the requirements of the respective cast operator is selected, even if it cannot be compiled (see example). If the cast can be interpreted in more than one way as static_cast followed by a const_cast, it cannot be compiled.
    In addition, C-style cast notation is allowed to cast from, to, and between pointers to incomplete class type. If both expression and new_type are pointers to incomplete class types, it's unspecified whether static_cast or reinterpret_cast gets selected.
    Edit : Grillé par jo_link_noir.

  8. #8
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Et bas je comprends pourquoi je ne venait plus sur le forum :p
    Donc pour vous malloc n'a rien a faire dans un programme C++....
    Tout comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (uint8*)::malloc(sizeof(CBuffer))
    Un void* perd la notion de const/volatile dont un C cast ne pause aucun problème.
    De plus niveau portabilité on en reparle :

    boost/smart_ptr/shared_ptr.hpp
    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
    #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
        ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
        ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
     
    // g++ 2.9x doesn't allow static_cast<X const *>(void *)
    // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
     
    template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
    {
        void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
        return const_cast<D *>(static_cast<D const *>(q));
    }
     
    #else
     
    template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
    {
        return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
    }
    #endif
    NB : RTTI et performance je pensais au dynamic_cast et pas au reinterpret_cast effectivement.

  9. #9
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    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 296
    Par défaut
    Là on est sur des compilateurs qui prédatent le standard de 1998. On s'en fout un peu de la compatibilité avec ces bêtes.

    Un ligne importante dans les casts C: ils dégénèrent avec des déclarations anticipées. C'est de fait une excellente raison pour les bannir. Hors RTTI, static_cast et reinterpret_cast feront le même boulot et sans ambiguïté. Et dans le cas du RTTI ... n'en parlons même pas, ils ne peuvent pas se substituer à dynamic_cast. Ils en sont incapables.
    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...

  10. #10
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    http://en.cppreference.com/w/cpp/language/explicit_cast

    Les cast C fonctionne très bien avec les forward déclarations.
    In addition, C-style cast notation is allowed to cast from, to, and between pointers to incomplete class type. If both expression and new_type are pointers to incomplete class types, it's unspecified whether static_cast or reinterpret_cast gets selected.

  11. #11
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    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 296
    Par défaut
    Pour toi "unspecified" veut dire "marche bien" ? :/

    Ta définition est pour le moins singulière: http://www.linguee.fr/anglais-franca...specified.html

    J'achète "marche à moitié". Mais "bien", certainement pas.
    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...

  12. #12
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Citation Envoyé par Astraya Voir le message
    Et bas je comprends pourquoi je ne venait plus sur le forum :p
    Je te comprends, les gens sont aigris .

    Citation Envoyé par Astraya Voir le message
    Donc pour vous malloc n'a rien a faire dans un programme C++....
    Oui. malloc n'apporte pas les garanties qu'offre new, notamment celle d'allouer un type et non un espace mémoire: il est aisé de ne pas faire correspondre sizeof(T) avec le cast qui précède. Cela parait con, mais c'est une erreur difficile à diagnostiquer.
    De plus, l'utilisation de malloc oblige d'utiliser l'opérateur new pour la construction (emplacement new). L'oublier, c'est prendre un risque.
    Après, rien n'empêche d'utiliser ::operator new pour faire comme malloc: allouer un espace mémoire. Mais c'est un besoin très particulier où la mémoire n'est pas utilisé immédiatement. Les conteneurs de la SL le font à travers des allocateurs.
    Pour terminer ::operator new peut prendre des paramètres, le standard propose une version sans exception par exemple. Il est aussi possible d'interdire l'utilisation de new sur certains objets.

    Citation Envoyé par Astraya Voir le message
    Tout comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (uint8*)::malloc(sizeof(CBuffer))
    Clairement. Cela reprend ce que je disais juste au-dessus: le cast et la taille du type demandé peuvent ne pas correspondre. Reste que si c'est légitime, rien ne l'indique non plus.
    Je trouve beaucoup plus judicieux d'utiliser new uint8_t[sizeof(CBuffer)].

    Citation Envoyé par Astraya Voir le message
    Un void* perd la notion de const/volatile dont un C cast ne pause aucun problème.
    void ne perd pas le qualificatif, mais le type. Passer d'un void const * en T * est un problème.

    Un autre reproche du C-cast: il accepte sans broncher quasiment tous les changements qui peuvent intervenir en amont. Même quand ceux-ci invalident la suite comme l'ajout de const qui sont supprimés par le cast.

  13. #13
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Mais ce qui m'agace par dessus tout c'est d'entendre des "jamais utiliser ca" de la part d'un développeur. Pour moi c'est du même niveau que "toujours utiliser ca" ( Le concept de la "balle en argent" mais à l'envers ).
    Alors le "jamais" ne devrais "jamais" (:p) avoir lieu, surtout pas dans un milieu comme le développement. Ça pu la programmation de SSII ce genre de discours.

    Quand je vois un void* et que je vois un (T*) derrière c'est tout à fait legit.

    Voila c'est tout c'était mon coup de gueule contre les jamais c'est pas bien blablabla...

  14. #14
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    En attendant, tu n'as n'as toujours pas donné un seul argument contre les casts C++ (sauf un problème de compatibilité avec les compilateurs d'il y a 20 ans qu'on se fout pas mal).
    Ni un seul argument en faveur du cast C.

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

Discussions similaires

  1. Conversion de XML en objet (JAXB en Java) ?
    Par elgaied dans le forum Qt
    Réponses: 0
    Dernier message: 11/02/2013, 15h10
  2. Cast void* - Objet C++
    Par LaMainSurLeKatana dans le forum C++
    Réponses: 5
    Dernier message: 24/08/2010, 13h09
  3. Conversion de string en Objet (zone de texte)
    Par Secco dans le forum VBA Access
    Réponses: 3
    Dernier message: 07/05/2008, 20h17
  4. Question bateau sur la conversion si possible d'objets
    Par kenny49 dans le forum Langage
    Réponses: 1
    Dernier message: 08/08/2007, 19h20
  5. Socket (SMTP) vers objet MimeMessage : conversion ?
    Par Loicb dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 06/12/2004, 18h21

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