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

Langage C++ Discussion :

Pointeurs et références + template et spécialisation


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Par défaut Pointeurs et références + template et spécialisation
    Bonjour à tous,

    Je vous pose aujourd'hui une question qui je pense est assez simple, mais comme je ne sais pas quoi taper sur internet je n'ai rien trouvé à ce sujet.

    Imaginons une classe A, contenant un accesseur sur référence constante J'initialise un pointeur sur cette classe puis je déclare un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const int& variable = a.getX()
    Je détruis le pointeur sur la classe A et évidemment la variable référence n'est plus valide. Mon problème est le suivant : comment détecter que r n'est plus valide sans provoquer un crash du programme ?

    Si vous voulez je peux vous expliquer pourquoi je voudrais savoir ça mais je ne le fais pas ici car cela ne me semble pas nécessaire à la résolution du problème.
    J'ajoute également que je préfère l'utilisation de pointeurs permettant beaucoup plus de souplesse car il suffit d'un pour savoir si le pointeur est valide.



    Je poste également un autre problème afin de ne pas trop surcharger le forum même si ce problème n'a pas grand chose à voir avec le précédent.
    Je serai assez bref : imaginons une classe template A :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename T>
    class A
    {
    //du code
    }
    Maintenant imaginons une classe B templatée comportant une fonction template dont le paramètre template pourrait être la classe A avec un paramètre template indéterminé (je sais c'est lourd mais comment expliquer ça autrement ).
    Cela donnerait quelque chose comme ça (même si la ça ne compile pas évidemment)
    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
     
    class B
    {
        //du code
     
        template <typename T, typename U>
        void faireqqch(T<U> machin);
    }
     
    template <typename T, typename U>
    void B::faireqqch(T<U> machin)
    {
        //faire qqch
    }
     
    template <>
    void B::faireqqch(A<T> specialisationclasseATemplateEnT)
    {
        //faire qqch
    }
    Sachant que l'action à réaliser dans le cas de la spécialisation de B avec le paramètre A<T> pourrait être la même quelque soit T !

    Merci par avance

  2. #2
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Salut,

    Pour la première question, c'est une question de design, je pense que tu devrais nous montrez ce que tu essayes de faire, pour voir dans quel cas tu te trouves. Néanmoins, une référence constante ne devrait pas être utilisée sur un type primitif car léger à copier et tu gagnes en performance mais sur des objets plus volumineux.

    Pour la seconde question, il s'agit du template de template :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template <template<class> class T, class U>
        void faireqqch(T<U> machin);
    Et puis après tu peux spécialiser en fonction de T avec Quelquechose<U>. Mais peut-on savoir ce qui justifie cette opération assez rare en C++ ?

  3. #3
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Par défaut
    Tout d'abord merci pour ta réponse

    En ce qui concerne le premier problème je me suis documenté sur l'amitié en c++ et j'ai trouvé un moyen bien meilleur pour effectuer ce que je cherchais, il est vrai que la référence était ici inutile (tout comme le pointeur d'ailleurs).

    Pour mon second problème, je vais essayer de t'expliquer.
    En fait je fais actuellement un minijeu consistant à envoyer des missiles avec une certaine puissance et un certain angle sur la maison adverse tour à tour. Le missile suit une trajectoire réaliste prenant en compte les paramètres physiques qui régissent son mouvement (poids, frottements, vitesse, accélération ...). Entre les maisons des 2 joueurs se trouve un relief créée aléatoirement et interpolé de la manière voulue par l'utilisateur (linéaire, cosinusoidale ou cubique).
    J'essaie je bien coder ce tout petit jeu et pour cela je veux me doter d'un gestionnaire de collisions capable de détecter des collisions entre plusieurs classes héritant d'une classe BoundingBox (abstraite) : SimpleRectBox, SpriteSimpleRectBox (je code le jeu avec la SFML), ComplexRectBox(pour gestion des angles), SpriteComplexRectBox et d'autres encore. Le gestionnaire de collision sera également capable de détecter la collision entre une BoundingBox et une courbe quelconque en calculant notamment des distances aux courbes.

    Voila pour l'exposition de ce que je souhaite faire
    Maintenant voila comment je conçois mon gestionnaire : il s'agirait selon moi d'une méthode templatée (placée dans un namespace éventuellement)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template <typename U, typename V>
    bool IsCollision(U& boundingBox, V& otherBoundingBox)
    Cette méthode serait spécialisée pour chaque couple U,V de boundingBox et retournerait false lorsque le couple ne serait pas spécialisé. Cette méthode serait également autorisée à accéder aux données des différentes BoundingBox (d'où le friend).

    Or certaines BoundingBox sont templatées, notamment parce que le type sf::Rect de la SFML l'est.
    Donc mon gestionnaire de collisions doit prendre en compte ces classes sans leur assigner un paramètre template différent pour chaque spécialisation de la méthode de collisions (ce qui serait terriblement redondant et laid).
    D'où ma deuxième question

    CQFD (j'espère que vous aurez compris mon raisonnement )

    Ce design est-il à revoir ? Si oui n'hésitez pas à m'en indiquer de nouveaux


    Edit : En fait j'aimerais quand même bien savoir pour ma première question car imaginons qu'une classe A comporte une référence vers une autre classe B, et que cette dernière, allouée dynamiquement, est détruite . Comment faire pour interdire l'accès à une méthode de cette classe détruite depuis la classe A qui dispose toujours de sa référence sur la classe B invalide ?

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <>
    void B::faireqqch(A<T> specialisationclasseATemplateEnT)
    {
        //faire qqch
    }
    La spécialisation partielle n'est possible que pour les classes, fonction libres et méthodes peuvent être spécialisées totalement uniquement.

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Je reviens en vitesse sur l'accesseur...

    Outre le fait que tu as, ici, beaucoup plus facile de renvoyer directement un entier plutôt qu'une référence constante sur un entier, une habitude particulièrement saine à prendre est de déclarer toutes les fonctions membres qui n'ont pas vocation à modifier l'objet au départ duquel elles sont appelées (c'est, entre autres, le cas de tous les accesseurs ) comme étant des fonctions membres constantes.

    Leur déclaration se faisant sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class MaClass
    {
        publc:
            Type /* const & */ doSomething() const;
    }
    Evidemment, si l'implémentation n'est pas inline, elle prendra la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Type /* const & */ MaClass::doSomething() const
    {
        // ce qui doit etre fait
    }
    De cette manière, si, pour une raison ou une autre, tu venais à vouloir faire quelque chose que la constante interdit (il est très facile d'oublier de déclarer le retour comme étant constant alors qu'on déclare que c'est une référence ) le compilateur t'insultera et attendra que tu corriges ton code
    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

  6. #6
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Par défaut
    Ok merci j'ai mieux compris l'intérêt des accesseurs référence constante

    Sinon pour mon problème de template et de collision le fait que je ne puisse pas faire de spécification partielle m'empêche donc de faire ça (enfin ça ne m'empêche pas de le faire mais c'est juste que ça ne fonctionnera pas comme je le souhaite) :

    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
     
    //est utilisé par défaut
    template <template<class> class T, template<class> class U, class V, class W>
    bool CollisionManager::IsCollision(T<V>& boundingBox, U<W>& otherBoundingBox)
    {
        std::cout<<"ca passe pas par la spécialisation partielle "<<std::endl;
        return false;
    }
     
    namespace CollisionManager
    {
    //n'est jamais utilisé
    template <class V, class W>
        inline bool CollisionManager::IsCollision(SimpleRectBox<V>& boundingBox, SimpleRectBox<W>& otherBoundingBox)
        {
            std::cout<<"ca passe bien par la spécialisation partielle"<<std::endl;
            return true;
        }
     
    //est utilisé quand c'est possible
    template <>
        inline bool IsCollision(SimpleRectBox<int>& boundingBox, SimpleRectBox<int>& otherBoundingBox)
        {
            std::cout<<"ca passe bien par la spécialisation totale qui n'est pas ce que je cherche"<<std::endl;
            return true;
        }
    }
    Cela m'embête bien car c'est la deuxième fonction qui m'intéresse, je n'ai pas envie de définir IsCollision(SimpleRectBox ..., SimpleRectBox...) pour chaque type possible, comme pour la troisième fonction !

    Est-ce possible de contourner le problème ? Ou bien dois-je revoir mon design ?

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    En programmation générique (et, à bien y penser, en programmation orientée objet aussi, d'ailleurs ) , il faut savoir que tout problème peut se résoudre en rajoutant une abstraction supplémentaire

    Si tu veux pouvoir spécialiser le comportement de isCollision, crées une politique et des traits de politique :
    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
    template <typename First, typename Second>
    struct IsCollision;
    template <typename Second>
    struct IsCollision <Rect, Second> // une collision entre un rectangle et n'importe quoi
    {
        bool operator()(SimpleRectBox<Rect> & first, SimpleRectBox<Second> & second)
        {
            /*   ...   */
        }
    };
    struct IsCollision <Triangle, Circle> // une collision entre un Triangle et un cercle
    {
        bool operator()(SimpleRectBox<Rect> & first, SimpleRectBox<Circle> & second)
        {
            /*   ...   */
        }
    };
    /* ... */
    utilisée sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <class V, class W>
        inline bool CollisionManager::IsCollision(SimpleRectBox<V>& boundingBox, SimpleRectBox<W>& otherBoundingBox)
        {
            return IsCollision()(boundingBox, otherBoundingBox);
        }
    j'ai écrit il y a quelques temps maintenant toute une prose dont tu pourrais t'inspirer, même si elle traitait de points et de bipoint, pour expliquer le raisonnement à suivre
    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

  8. #8
    Membre éclairé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2011
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2011
    Messages : 274
    Par défaut
    Ahah sacré laïus effectivement

    Merci beaucoup pour cette explication j'avais déjà vu quelques trucs sur les classes de trait et politique sans en comprendre l'utilité, je pense que grâce à ça je vais pouvoir enfin saisir ces concepts

    Je regarderai ton exemple demain à tête reposée car cela me paraît assez compliqué tout de même mais c'est ce qui rend ce langage beau . C'est assez fabuleux quand on pense à toutes les possibilités offertes par ce langage dont on sait qu'on ne pourra jamais toutes les découvrir

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

Discussions similaires

  1. Transmission de pointeur par référence
    Par bertry dans le forum Débuter
    Réponses: 3
    Dernier message: 06/10/2008, 17h45
  2. [Débutant] Passage de pointeur et classe template
    Par guigouz dans le forum Langage
    Réponses: 3
    Dernier message: 18/04/2008, 14h58
  3. pointeurs et références quoi choisir ?
    Par damien77 dans le forum C++
    Réponses: 23
    Dernier message: 11/03/2008, 21h17
  4. Pointeur sur référence ?
    Par koala01 dans le forum C++
    Réponses: 24
    Dernier message: 15/01/2008, 17h54
  5. pointeur ou référence
    Par damien77 dans le forum C++
    Réponses: 2
    Dernier message: 23/03/2007, 16h43

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