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 :

héritage et stl::vector


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut héritage et stl::vector
    Bonjour alors voilà mon problème :

    J'ai une classe Bomb qui dérive de la classe Item :

    mon bomb.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Bomb : public Item {
    	public:
    		Bomb(int x, int y, int bomb_type);
    		void Launch();
    	private:
    		int bomb_type;
    };
    mon bomb.cpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Bomb::Bomb(int _x, int _y, int _bomb_type) : Item(_x, _y, 3), bomb_type(_bomb_type) {
     
    }
     
    void Bomb::Launch() {
    	// some code
     
    }
    et voici enfin mon item.h :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Item {
     
    public:
    	Item(int x, int y, int type);
    	~Item();
    	sf::Sprite getSprite();
    private:
    	int x, y, type;
    	sf::Image image;
    	sf::Sprite sprite;
    };
    Donc voilà le problème est le suivante, dans mon code, il se trouve que j'ai un vector de vectors qui contiennent des Items, il déclaré comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	std::vector< std::vector<Item*> > map_tableau_sprites;
    et initialisé ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	std::fill( map_tableau_sprites.begin(), map_tableau_sprites.end(), std::vector<Item*>(32, NULL));
    lorsque je le remplis ensuite avec des Item, pas de soucis, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	for(i = 0; i <= 31; i++) {
    		for(j = 0; j <= 31; j++) {
    			//si la case est 0, on crée un Item vide.
    			//si la case est à 1 alors on initialise un objet de type indestructible.
    			//si la case est à 2 alors un initialise un objet de type destructible.
    				map_tableau_sprites.at(i).at(j) = new Item(i*25, j*25, map_tableau.at(i).at(j));			
    		}
    	}
    mais là où j'obtiens une erreur, c'est quand j'inclus dans ce tableau un object de type Bomb et que j'essaie de faire appel à la méthode Launch(), il me dit 'class Item' has no member named 'Launch' lorsque je fais ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	map_tableau_sprites.at(x).at(y) = new Bomb(x*25, y*25, 0);
    	(*map_tableau_sprites.at(x).at(y)).Launch();
    (l'erreur est relative à la seconde ligne)

    Si vous avez une idée de la marche à suivre pour régler ça je suis preneur, je me suis renseigné du coté des "virtual" ou "friend" mais je ne vois pas trop l'appliquer sans être lourd (aka toucher ma classe Item mais peut-être est-ce nécéssaire)

  2. #2
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Hello !

    Dans ton code, l'élément qui parait faible c'est ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::vector< std::vector<Item*> > map_tableau_sprites;
    vector de vector, c'est pas toujours une bonne idée. En général tu t'en sortirais mieux en faisant une class avec l'operator()(int i, int j) qui va chercher dans un unique vector. C'est surtout vrai si tes lignes ont le même nombre de colonnes !

    Ensuite, il y a le Item*... vector ne détruira pas tout seul les pointeurs lors de sa destruction, donc ATTENTION ! Pourquoi pas Item tout court ? Tu as des Item à partager dans ton code? Si c'est le cas, il vaut mieux utiliser des shared_ptr. Si ce n'est pas le cas, Item tout court et tu t'éviteras bien des problèmes...

    EDIT :
    Pour ton problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (*map_tableau_sprites.at(x).at(y)).Launch();
    est à remplacer par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    map_tableau_sprites.at(x).at(y)->Launch();
    c'est plus joli. Par contre, il faut une méthode virtuelle Launch dans item aussi, sinon le polymorphisme ne marche pas ! Ou bien tu fais un static_cast, mais c'est pas joli joli !

  3. #3
    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 n'ai lu qu'en diagonale, mais, il est sommes toutes logique que, si tu connait l'ensemble des éléments de ton tableau comme étant... des Items, ils soient considérés comme tels lorsque tu parcoure ton tableau.

    Du coup, tu ne peux utiliser la bombe qui passe pour un être un Item que... comme un Item, et tu ne peux donc envisager d'invoquer que les fonctions de bombe qui font partie de... l'interface public d' Item

    Si tu veux récupérer les possibilités offertes par l'interface publique de bombe (ici, le fait d'invoquer la fonction launch) mais qui n'ont rien à voir avec celles fournies par l'interface public d'Item, il faut effectuer un transtypage ("downcast" pour être précis) de ton pointeur de type Item en un pointeur de type bombe.

    Cependant, la nécessité de recourir au downcasting est souvent le symptôme d'un problème de conception, et il vaut donc sans doute mieux essayer de réfléchir plus profondément au moyen de le résoudre.

    Ainsi, une des solution pour résoudre ce "petit" problème pourrait être de se baser sur le fait que, tous les objets (Items) que tu utilise peuvent être... utilisés, et que l'utilisation qui en est faite doit s'adapter au type réel de l'objet.

    Tu pourrais donc envisager l'ajout d'une fonction virutelle "use" dans ta classe Item, qui serait appelée chaque fois que tu veux... utiliser un objet (de manière générale), et dont le comportement s'adaptera en fonction du type dynamique de l'objet que tu veux utiliser

    A titre d'exemple, pour ta classe bombe, la fonction use se contenterait d'appeler... launch

    Comme on ne peut pas vraiment définir un comportement "minimal commun" à tous les objets pour cette fonction, il faudrait la déclarer virtuelle pure (ce qui transformera de facto Item en classe abstraite et obligera donc à définir use pour chaque nouvelle classe qui en dérive et que l'on souhaite pouvoir instancier )

    Au final, tu aurais donc une classe Item ressemblant à
    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
    class Item {
     
    public:
    	Item(int x, int y, int type);
            /* attention: le destructeur d'une classe de base pour les objets
             * polymorphes doit etre public et virtuel ou protégé et non virtuels
             */
    	virtual ~Item();
    	sf::Sprite getSprite();
            /* c'est une fonction virtuelle pure: nous indiquons au compilateur
             * que nous ne disposons pas des éléments nécessaires pour 
             * donner une implémentation de base à la fonction
             *
             * cette fonction transforme Item "classe abstraite"
             */
            virtual void use() = 0; 
    private:
    	int x, y, type;
    	sf::Image image;
    	sf::Sprite sprite;
    };
    (Au passage, j'attire ton attention sur le fait que le destructeur d'une classe servant de base à des objets polymorphes doit être public et virtuel ou protégé et non virtuel, afin que le comportement lié au destructeur s'adapte correctement au type réel de l'objet)

    Et tu aurais la classe Bomb qui ressemblerait à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Bomb : public Item {
    	public:
    		Bomb(int x, int y, int bomb_type);
                    virtual ~Bomb();
    		void Launch();
                    /* pour pouvoir instancier une bombe, il faut que toutes les
                     * fonctions virtuelles pure de Items soient redéfinies.
                     *
                     * ca tombe bien, l'utilisation d'une bombe consiste à... la lancer
                     */
                    virtual void use();
    	private:
    		int bomb_type;
    };
    Si, plus tard, tu veux créer un autre objet "arc" ou "fusil", le comportement "normal" associé à son utilisation, c'est "tirer" et tu auras donc sans doute une fonction "shoot".

    Pour pouvoir instancier ton arc ou ton fusil, il faudra... redéfinir la fonction use en faisant en sorte qu'elle... invoque la fonction shoot qui ira si bien
    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

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    Bonjour, merci pour vos réponses, à vrai dire je viens du ruby où l'héritage et le polymorphisme est clairement plus souple, j'ai un peu de mal donc ;-)

    Ben le vector de vector m'arrange bien pour le coup puisque je peux me représenter dans ma grille (x,y),

    pour l'histoire de Item* je pensais utiliser delete par la suite.

    En rajoutant les virtual en en définissant mes destructeur et mes Launch() comme il faut ça compile et link donc niquel merci à vous !

  5. #5
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Ben le vector de vector m'arrange bien pour le coup puisque je peux me représenter dans ma grille (x,y),
    Sa se fait aussi avec un vector a un niveau. Pas besoin de deux.

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    Hello, du coup oui j'aimerais bien utiliser un unique vector et pas des vector de vector,

    je vois pas trop comment utiliser operator()(int i, int j) pour rechercher dans mon tableau, j'ai aussi regardé du coté de stl::find et stl::find_if mais je ne comprends pas trop au niveau des prédicats etc vu qu'il faut que je compare i et j

    Est-ce que vous pourriez me donner des piste sur la manière de rechercher dans mon vector ?

    Merci par avance

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    318
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 318
    Par défaut
    Citation Envoyé par chollier Voir le message
    Hello, du coup oui j'aimerais bien utiliser un unique vector et pas des vector de vector,
    ...

    Est-ce que vous pourriez me donner des piste sur la manière de rechercher dans mon vector ?

    Merci par avance
    tu peux faire un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    item * GetItem(unsigned int  i, unsigned int j)
    {
          item * l_pReturn(NULL);
          if (j*length+ i < map_tableau_sprites.size()) // length taille de ton sous vecteur
          {
                   l_pReturn = map_tableau_sprites[j*length+ i];
          }
          return l_pReturn;
    }

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    Hello,

    Merci pour ta réponse, mais fait, je n'utilise plus uniquement map_tableau_sprite,

    maintenant j'ai 5 vecteur :

    Un contenant les images de background, contenant des pointeurs vers des objets de type Item
    un pour les fixed_items, contenant des pointeurs vers des objets de type Item
    un pour les destructible_items, contenant des pointeurs vers des objets de type Item
    un pour les bonus, contenant des pointeurs vers des objets de type Bonus (bonus descendant de item)
    et un pour les bombes, contenant des pointeurs vers des objets de type Bomb (bomb descendant de item)

    J'ai un autre tableau de tableaux qui ne contiennent que des int et qui me permet de savoir exactement quel type d'objet est à quel endroit.

    donc idéalement j'aimerais pouvoir par exemple faire une recherche dans les destructible_items en donnant en paramètre i et j et qu'il me retourne le pointeur vers cet objet (de type Item)

    Je suis en train de regarder au niveau des foncteur, prédicats et bind1st / bind2nd, je pense qu'il faut que j'utilise ça pour faire mes recherches mais je galère quand à la manière de m'y prendre, on voit surtout des exemples pour du tri sur le net :/

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    C'est bon du coup je m'en suis sorti en créant une fonction dérivée de std::binary_function, c'est un peu complexe à saisir mais ça le fait ;-)

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

Discussions similaires

  1. Probleme avec la STL(vector) avec code C
    Par Benjy dans le forum SL & STL
    Réponses: 12
    Dernier message: 06/04/2006, 12h54
  2. Probleme avec parcours de stl::vector
    Par MDiabolo dans le forum SL & STL
    Réponses: 10
    Dernier message: 08/03/2006, 00h35
  3. STL vector addition
    Par dj.motte dans le forum SL & STL
    Réponses: 1
    Dernier message: 08/11/2004, 08h25
  4. [STL] vector<string> et appel de fonctions.
    Par guejo dans le forum MFC
    Réponses: 4
    Dernier message: 08/10/2004, 17h36
  5. STL::vector crash a l"execution
    Par sebA dans le forum MFC
    Réponses: 2
    Dernier message: 16/06/2004, 16h36

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