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 :

Petite question à propos de l'héritage et des templates.


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Petite question à propos de l'héritage et des templates.
    Salut,

    je voudrais savoir si il est possible de récupérer le type d'un objet dérivé à partir de la classe de base en c++ afin de l'insérer dans un template.

    J'ai une classe BoundingVolumeBase qui me sert juste à stocker un tas de volumes englobants de type différents :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    class BoundingVolumeBase {
    }

    Ma classe BoundingVolume est template, donc, et je veux pouvoir stocker des volumes enfants de n'importe quel type, je fais donc hériter cette classe de BouningVolumeBase et j'utilise type erasure :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    template <typename D>
    class BoundingVolume : public BoundingVolumeBase {
    private :
        std::vector<BoundingVolumeBase*> children;
        typedef D& type;
    };

    Pour caster les objets de type BoundingVolumeBase en BoundingVolume<D> j'ai besoin de connaitre le type de D à la compilation, je suis donc obligé de faire ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    class BoundingVolumeBase {
             virtual std::string getType() = 0;
    }

    Et de redéfinir cette méthode dans ma classe BoundingVolume et dans toutes les classes héritant de boundingvolume, ainsi je peux connaitre le type et faire un downcast à l'aide d'un if :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    template<typename C>
    bool intersects(BoundingVolume<C> other) {
           if (children.size() == 0 && other->children.size() == 0) {
                  return intersects(*static_cast<C*>(other));
           } else if (children.size() == 0 && other->children.size() != 0) {
                  for (unsigned int i = 0; i < other->children.size(); i++) {  
                        if (other->chirldren[i]->getType() == "BoundingBox") {
                             if (intersects(static_cast<BoundingVolume<BoundingBox>*>(other->children[i])))
                                 return true;
                        }   
                  }
           }      
    }

    Mais ceci me parait assez lourd à faire surtout si j'ai beaucoup de classes qui héritent de BoundingVolume, j'aimerais savoir si en c++11 il n'y a pas moyen de récupérer le type de la sous classe à partir de la classe de base et faire un truc comme ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if (intersects(static_cast<BoundingVolume<other->children[i]->getType()>*>(other->children[i])))
           return true;

    Voilà merci.

  2. #2
    Membre éclairé
    Homme Profil pro
    Doctorant en Astrophysique
    Inscrit en
    Mars 2009
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Astrophysique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2009
    Messages : 312
    Par défaut
    Du CRTP ça passerait à tout hasard ? (http://en.wikipedia.org/wiki/Curious...mplate_pattern)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    template <class Derived>
    class BoundingVolumeBase {
    }
     
    template <typename D>
    class BoundingVolume : public BoundingVolumeBase<BoundingVolume<D>> {
    private :
        std::vector<BoundingVolumeBase<BoundingVolume<D>>*> children;
        typedef D& type;
    };
    Ou bien simplement passer D, à la classe de base ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <typename D>
    class BoundingVolumeBase {
    }
     
    template <typename D>
    class BoundingVolume : public BoundingVolumeBase<D> {
    private :
        std::vector<BoundingVolumeBase<D>*> children;
        typedef D& type;
    };

  3. #3
    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
    Regarde le double disptach et le pattern visitor (boost.visitor ?).

    Rien de simple à l'horizon, j'en est bien peur.

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Le plus simple dans ce cas-là, mais franchement je recommenderais pas trop.
    Tu fais un enum, qui liste tous les types.

    Tu as une méthode virtuelle qui retourne l'entrée d'enum correspondante.


    Mais ça indique le plus souvent juste un mauvais design que de devoir recourir à ça. Ou une méconnaissance du C++ et de l'objet en général.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    La suggestion de templater la classe de base est intéressant, car tu n'as probablement pas de raison valable de grouper des BoundingVolume de D différentes.

    Tu peux aussi avoir une classe intermédiaire:
    • BoundingVolumeBase, qui propose des méthodes virtuelles (pures?) comme centre() et contient(x, y, z).
    • BoundingVolume<T> : public BoundingBase, qui permet d'accéder à son contenu de type T
    • BoundingSphere<T> : public BoundingVolume<T>, qui gère une sphère de collision.



    Cela dit, les calculs mathématiques d'intersections sont différentes de selon les deux volumes à considérer.
    La théorie est :
    soit V1(x,y,z) la fonction déterminatrice du premier volume, valant 0 si le point (x,y,z) est hors du volume, 1 sinon.
    soit V2(x,y,z) la déterminatrice du second volume.
    les volumes sont en intersection si et seulement si l'intégrale de V1*v2 dx dy dz est non nulle.

    En pratique, on fait autrement:
    • pour deux sphères, on calcule la distance entre les centres, qui doit être plus grandes que la somme des rayons
    • pour deux cubes alignés sur les axes (AABB: Axis Aligned Bounding Box), on calcule les projections sur les trois axes de cette distance, et on vérifie qu'elles sont plus grandes que les "rayons" dans ces directions.
    • pour des ellipsoïdes, c'est un peu pareil
    • avec des cylindres verticaux, on compare les hauteurs et altitudes, puis la distance en négligeant la verticale (x2-x1)²+(y2-y1)² < (r1+r2)²

    Si les volumes sont convexes, on approxime par l'une de ces formules.
    Si certains sont concaves, on pleure, ou on découpe par morceaux.

    On peut aussi prendre plusieurs volumes de détection, par exemple un cube externe et un sphère interne.

    L'idée des volumes englobants (AABB et sphères) c'est de permettre des calculs rapides, soit en séparant les trois axes, soit en supprimant la notion de direction.

  6. #6
    Invité
    Invité(e)
    Par défaut
    Ok, je vais essayer ça.

    Le fait que je ne passe pas le template à la classe de base est parce que je veux avoir un seul type de base pour pouvoir stocker tout mes différents type de volume dans une seule et même collection afin de former une hiérarchie de volumes englobants, ainsi par exemple je peux mettre une AABB autour du corps, une Ellipsoïd autour du bras, etc...
    Le problème avec le template c'est que il peut être de tout type.

    Mon idée de départ était donc de combiner le pattern CRTP et le type erasure. (Principe de boost any)

    J'utilise en effet plusieurs techniques différentes pour détecter l'intersection suivant le type du volume. (Ca dépend de la complexité du volume)

    Il est vrai que je pourrai aussi utiliser boost::variant et les visitors, ça m'éviterais de devoir faire une enum. (ou ce genre de chose)

    Ok bah j'essayerai ça si ce n'est pas trop compliqué à implémenté.

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

Discussions similaires

  1. Petite question à propos des RichTextBox.
    Par Jeano81 dans le forum VB.NET
    Réponses: 26
    Dernier message: 16/03/2015, 17h03
  2. [Javamail] Petite question à propos des Flags
    Par Hellnino18 dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 26/05/2009, 08h49
  3. Petite question à propos du redbook...
    Par Michaël dans le forum OpenGL
    Réponses: 3
    Dernier message: 04/11/2004, 12h54
  4. Petite question à propos d'une requete
    Par ViBy dans le forum Langage SQL
    Réponses: 4
    Dernier message: 15/09/2004, 12h21

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