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 :

Pointeurs et héritage - descendre le niveau d'un pointeur?


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné

    Homme Profil pro
    Consultant ERP
    Inscrit en
    Janvier 2013
    Messages
    372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant ERP
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2013
    Messages : 372
    Par défaut Pointeurs et héritage - descendre le niveau d'un pointeur?
    Bonjour,

    Un problème rapide :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Class A
    Class B : public class A
    Class C : public class B
    Je cherche à accéder, à l'aide d'un pointeur vers A d'une instance C, à des méthodes de cette instance déclarées en C.
    1ère question : Pour une instance donnée, est ce que le pointeur vers A est le même que celui vers C? (Je me doute de la réponse )
    2ème question : Est-il possible de "descendre" le niveau du pointeur de A vers C?

    J'ai essayé de déclarer la fonction virtuellement en A (sans la déclarer en B), mais la fonction réelle en C n'est pas appelée...
    Entendu parler de RAII et d'allocation dynamique de mémoire : y-a-t-il à creuser?

    Pour expliquer la raison du pointeur vers A je cherche à parcourir un plus grand nombre d'entités que les simples C, au cours d'un algorithme lourd.
    Récupérer le niveau de pointeur inférieur d'une autre façon prend beaucoup de temps.

    Merci!

  2. #2
    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
    Réponse à ta première question: oui, un C est un A, et son adresse est son adresse.
    Le compilateur appliquera de lui-même les éventuelles décalages.
    Sachant que dans ton cas précis (un seul héritage, et non virtuel), la partie A de C est bien au début de l'objet.
    Si on ne parle pas d'héritage virtuel, l'espace occupé par un objet est défini comme la suite des espaces occupés par ses classes de bases immédiates, dans l'ordre d'héritage, puis ses membres.

    Ainsi, avec struct Fille: M1, M2, M3 {int i;}, la mémoire d'un objet de type fille contient successivement M1, M2, M3 et i, avec éventuellement des espaces vide entre, pour des questions d'alignement.


    Pour que le code virtuel fonctionne, il faut un pointeur ou une référence vers A initialisée avec un B, et surout pas l'adresse d'un A.

    Pourrais-tu nous montrer un peu plus de code?
    Pourrais-tu nous dire comment tu peux savoir qu'un A est un C. ou même pourquoi tu veux ne t'occuper que des C d'un groupe de A?

  3. #3
    Membre chevronné

    Homme Profil pro
    Consultant ERP
    Inscrit en
    Janvier 2013
    Messages
    372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant ERP
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2013
    Messages : 372
    Par défaut
    Merci pour ces détails sur la gestion de la mémoire!

    Ma situation en détail est la suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    A class BaseGameEntity
     
    B class MovingEntity : public BaseGameEntity
     
    C class Bot : public MovingEntity
    Bot::isShooting(){return m_bIsShooting;}
    Je cherche à déterminer la cible d'un bot, pour cela je veux parcourir un conteneur d'entités incluant les autres bots, mais aussi les joueurs ennemis, les bâtiments... J'ai donc choisi d'effectuer une récursion au niveau de BaseGameEntity.

    Dans cet algorithme, un pointeur "iterator" pointe vers une instance BaseGameEntity, qui n'est pas forcément un bot.
    Je voudrais à partir de ce pointeur accéder à la méthode isShooting(); déclarée dans la classe Bot.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    		std::list<BaseGameEntity*> CloseDudes = bot->GetSensoryMem()->GetListOfCloseDudes();
    		std::list<BaseGameEntity*>::const_iterator curEnt= CloseDudes.begin();
    		while (curEnt != CloseDudes.end() // ... : initialisation de la récursion)
    		{
     
    				//...check if it is not the current target and is shooting...
    				(*curEnt) != bot->GetTargetBot() && (*curEnt)->isShooting() )
    			{
    Seulement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (*curEnt)->isShooting()
    renvoie une erreur

  4. #4
    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
    C'est bien ce que je pensais.
    Donnes-toi une liste des bots. Ca a un vrai sens pour le jeu.
    Les bots sont des éléments très différents d'un mur ou d'une caisse: ils sont certes physiques, mais ils agissent.

    Le concept que tu cherches a un nom, le downcasting.
    Tu peux avoir une fonction virtuelle asBot, définie dans la classe de base par un throw, et dans Bot pour retourner *this.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class base{
    public:
        struct im_not_a_bot{};
     
        virtual base const& asBot() const {throw im_not_a_bot();}
        virtual base& asBot() {throw im_not_a_bot();}
    };
     
    class bot: public base{
    public:
        bot const& asBot() const {return *this;}
        bot& asBot() {return *this;}
    }
    Cela dit, si tu le mets en place, c'est une usine à plantage.
    Je te conseille très très fortement à avoir une liste des bots.

  5. #5
    Membre chevronné

    Homme Profil pro
    Consultant ERP
    Inscrit en
    Janvier 2013
    Messages
    372
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant ERP
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2013
    Messages : 372
    Par défaut
    Mes tours aussi peuvent être ennemies!

    Limpide, merci!
    Mise en garde bien reçue

  6. #6
    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
    Alors si tes tours sont aussi des ennemis, envisage un héritage multiple.
    Je l'appelerai BadGuy, mais pas ShootingEntity, car le joueur peut tirer mais n'est pas un ennemi.

    Ainsi, une tour est une Entity et une BadGuyEntity, et un Bot un MovingEntity et un BadGuy
    Tu vas rapidement t'apercevoir que tu as besoin des positions de chacun, et donc que tu vas peut-être avoir besoin d'un héritage virtuel (en diamant)

    Une autre solution sera d'avoir une BadGuy qui sera templaté avec le type de BadGuy (nom de code CRTP)
    Ca donnerait ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class BaseGameEntity;
    class MovingEntity : public BaseGameEntity;
    class FixedEntity: public BaseGameEntity;
    class Bot : public MovingEntity, public BadGuy<Bot>;
    class Tower: public FixedEntity, public BadGuy<Tower>;
    On appelle ce motif CRTP pour curiously recurring template pattern ou modèle curieusement récursif.
    En effet, une classe C hérite d'une template dont le paramètre est C.
    L'intérêt, c'est que BadGuy peut utiliser le type précis de la classe.

    Voici un exemple de ce que pourrait être BadGuy:
    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 BasicBadGuy {
    proctected:
        BasicBadGuy() {}
    public:
        bool is_shooting() const;
        virtual void shoot();
    }
     
    template <typename CRTP>
    class BadGuy : public BasicBadGuy{
    private:
        CRTP& that;
    proctected:
        BadGuy(CRTP& that) : that(that) {}
     
    public:
        CRTP::position_type x() const {return that.x();}
        virtual void shoot();
    };
    L'avantage, c'est que tu disposes d'une classe non template (BasicBadGuy) pour remplir un conteneur avec à la fois les bots et les tours.
    De plus, tu pourras aussi définir des spécialisations de BadGuy en cas de besoin.

    C'est la voie suivie par la STL pour les streams.
    ios_base est une classe non template, dont hérite basic_ios<CharT, Traits>, dont héritent basic_ostream et basic_istream, dont ...

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

Discussions similaires

  1. Réponses: 21
    Dernier message: 26/07/2011, 12h08
  2. Comment descendre le niveau d'un element treeview au niveau racine
    Par dehorter olivier dans le forum Composants VCL
    Réponses: 2
    Dernier message: 25/10/2010, 08h44
  3. Containers pointeurs et héritage
    Par philagui dans le forum C++
    Réponses: 2
    Dernier message: 01/05/2006, 15h52
  4. Pointeur et héritage...
    Par Zenol dans le forum C++
    Réponses: 2
    Dernier message: 08/03/2006, 12h31
  5. Réponses: 8
    Dernier message: 04/08/2004, 14h17

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