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 :

Tableau stockant enum(int) ou pointeur


Sujet :

Langage C++

  1. #1
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 61
    Par défaut Tableau stockant enum(int) ou pointeur
    Bonjour à tous,

    Dans le cadre d'un projet de jeu 2D, je pense considérer les différentes entités du jeu sur des maps "parallèles" ; on a, dans le cas de ce bomberman, une map globale (qui affiche les différents blocs), une map avec les players, une map avec les bonus, etc...

    Chaque map hérite d'une classe mère abstraite, où je définis notamment le tableau permettant de la stocker. J'aimerais que chaque case contienne soit la valeur d'une enum (sous forme de int, FREE=0, etc...), soit un pointeur vers l'objet présent sur cette case. Ainsi, il me serait très simple de parcourir les différentes maps et d'afficher correctement la scène.
    Il me serait du coup également très simple de vérifier les morts de joueurs, etc...

    Savez-vous s'il est possible de faire cela, et comment ?
    Pensez-vous autrement qu'il s'agit d'une erreur de conception, et pourriez-vous m'aiguiller vers la meilleure façon de faire ?

    Merci d'avance

  2. #2
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 551
    Par défaut
    Bonjour,

    quand vous parlez de map, parlez vous vraiment d'une table d'association clef-valeur et donc pas exemple d'une std::map, ou 'map' signifie 'tableau 'pour vous comme le titre le laisse penser?

    Le fait d'avoir des 'maps' parallèles laisse à penser qu'il y a peut être un problème d'archi. Par exemple est-ce que le parallélisme des 'map' de joueurs et de bonus signifie-t-elle que cela permet 'indiquer le bonus de chaque joueur ?

    pour revenir à Tableau stockant enum(int) ou pointeur, si le seul cas ou il n'y a pas de pointeur est le cas 'libre', alors il existe le pointeur nul
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  3. #3
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 61
    Par défaut
    Ah non, quand je parle de map ce sont des maps de jeux.
    Le cas "FREE" n'est pas le seul, ça dépend en réalité des maps ; la map globale affiche chaque blog, et donc peut prendre 3 états (mais pas de pointeur). En revanche, la map joueur possède soit un pointeur soit NULL.

    Par ailleurs, chaque map possèdera un type de pointeur différent (Player* pour la map des joueurs, Bonus* pour la map des bonus, etc...). Comme j'ai déjà une classe abstraite, j'aimerais bien que l'attribut représentant le tableau soit lui aussi générique et présent dans cette classe (les méthodes retournant l'état d'une case l'étant aussi).

    Est-ce possible ?

  4. #4
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 551
    Par défaut
    il suffit d'utiliser une classe template
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    Ce genre d'"optimisation en taille" est possible avec les unions, mais ça fait partie du genre de choses qu'on évite de faire à moins d'en avoir absolument besoin.

    S'il le faut vraiment, tu peux utiliser boost::variant, qui encapsule ça.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 61
    Par défaut
    Et bien, ça semble marcher parfaitement avec une classe template ; merci !

  7. #7
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 61
    Par défaut
    Hum en fait, j'ai encore un petit problème ; chaque élément du jeu (joueur, bonus, bombe, ...) dérive d'une classe abstraite "Entity". Celle-ci contient un pointeur vers une CMap contenant celle-ci des pointeurs vers les objets instanciés.

    Plus concrêtement, un joueur aura un attribut contenant un pointeur vers sa propre map (comprendre map au sens graphique) ; cette map contiendra quand à elle des pointeurs vers chaque joueur, à l'endroit de leurs coordonnées.

    J'ai essayé quelques trucs mais j'ai toujours une erreur à la compilation :

    .\Player.cpp(33) : error C2027: utilisation du type non défini 'CMap<T>'
    1> with
    1> [
    1> T=CEntity *
    1> ]
    La classe CEntity est pourtant bien déclarée !

    Voici les différentes codes :

    Entity.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
    21
    22
    23
    24
    25
    26
    27
    28
     
    #ifndef _CENTITY_
    #define _CENTITY_
     
    template<typename T> class CMap;
     
    /*
    	Abstract class CEntity
    	Defines elements that can be herited by all entities (players, bombs, bonus)
    */
     
    class CEntity {
     
    	protected:
    		int m_posX;
    		int m_posY;
    		CMap<CEntity*>* m_pMap;
     
    	public:
    		virtual const int getPosX();
    		virtual const int getPosY();
    		virtual void setPosX(const int x);
    		virtual void setPosY(const int y);
    		virtual void setMap(CMap<CEntity*>* map);
     
    };
     
    #endif
    Map.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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #ifndef _CMAP_
    #define _CMAP_
     
    #include "config.h"
     
    /*
    	Abstract class CMap
    	Defines elements that can be herited for each map : 
    		- a map table (MAP_SIZE x MAP_SIZE)
    		- getters & setters methods
    		- init method
    */
     
    template <typename TableType> 
    class CMap {
     
    	protected: 
    		TableType m_mapTable[MAP_SIZE][MAP_SIZE];
     
    	public:
    		const TableType getCaseState(int x, int y);
    		void setCaseState(int x, int y, TableType caseState);
    		virtual void init() = 0;
     
    };
     
    template<typename TableType> const TableType CMap<TableType>::getCaseState(int x, int y) {
    	return m_mapTable[y][x];
    }
     
    template<typename TableType> void CMap<TableType>::setCaseState(int x, int y, TableType state) {
    	m_mapTable[y][x] = state;
    }
     
    #endif
    Enfin, j'essaie d'utiliser mon tableau dans la classe CPlayer comme suit :
    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
     
    void CPlayer::move(Direction direction) {
    	switch(direction) {
    		case UP:
    			m_posY--;
    			break;
    		case DOWN:
    			m_posY++;
    			break;
    		case LEFT:
    			m_posX--;
    			break;
    		case RIGHT:
    			m_posX++;
    			break;
    	}
     
    	m_pMap->setCaseState(this);
    }
    Auriez-vous une idée ? Merci d'avance

  8. #8
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 551
    Par défaut
    [QUOTE=NainTernaute;5110999].\Player.cpp(33) : error C2027: utilisation du type non défini 'CMap<T>' difficile de vous aidez puisque vous ne donnez pas la ligne de code en question

    ceci dit CMap<T> n'est pas utilisable tel quel (en dehors de la def de CMap bien-sûr) car T n'est pas connu

    m_pMap->setCaseState(this) n'est pas valide tout simplement parce que cette opération prends 3 arguments et non un seul
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  9. #9
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 61
    Par défaut
    La ligne 33 est justement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m_pMap->setCaseState(m_posX, m_posY, this);
    Autant pour moi pour les 3 arguments, mais ça ne marche pas mieux comme cela en fait. :/ Et je n'ai pas utilisé le type "T" mais bien "CEntity*" (voir dans ma classe CENtity) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CMap<CEntity*>* m_pMap;
    D'où mon incompréhension lors de cette erreur, qui complète est plus explicite :

    1>.\Player.cpp(33) : error C2027: utilisation du type non défini 'CMap<T>'
    1> with
    1> [
    1> T=CEntity *
    1> ]
    EDIT : Par ailleurs, lorsque j'essaie de faire un setMap j'ai cette erreur :

    1>.\Game.cpp(11) : error C2664: 'CEntity::setMap'*: impossible de convertir le paramètre 1 de 'CPlayersMap *' en 'CMap<TableType> *'
    1> with
    1> [
    1> TableType=CEntity *
    1> ]
    1> Les types pointés n'ont aucun rapport entre eux*; conversion nécessitant reinterpret_cast, cast de style C ou cast de style fonction
    Et les lignes concernées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m_player.setMap(&m_maps.getPlayersMap());
    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
     
    #ifndef _CPLAYERSMAP_
    #define _CPLAYERSMAP_
     
    #include "Map.h"
    #include "Player.h"
     
    class CPlayersMap : public CMap<CPlayer*> {
     
    	protected:
     
    	public: 
    		void init();
     
    };
     
    #endif
    Voici un lien vers mon code complet si ça peut aider à la résolution du problème : http://www.jeremy-dutheil.fr/projects/Bomber.rar

  10. #10
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 551
    Par défaut
    c'est simple : Map.h n'est pas inclue directement ou indirectement dans Player.cpp

    [edit]dans ma première réponse je n'avais pas osé demandé si CMap était bien inclue car cela paraissait tellement énorme, finalement j'aurais du [/edit]
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  11. #11
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 61
    Par défaut
    Bouarf, j'ai honte

    En revanche, quelque chose m'étonne toujours ; dans ma classe CEntity je définis cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    virtual void setMap(CMap<CEntity*>* map);
    Et ma classe PlayersMap comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    class CPlayersMap : public CMap<CPlayers*>
    Quand je fais cela, je ne peux pas appeler ma méthode setMap avec un pointeur vers mon objet de CPlayersMap ; en revanche, en définissant CPlayersMap comme suit ça marche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    class CPlayersMap : public CMap<CEntity*>
    Je pensais que le fait que la fonction soit virtuelle lui permettrait de s'adapter aux classes dérivées de CEntity automatiquement, ai-je loupé quelque chose ?

    En tout cas, merci pour l'aide apportée.

  12. #12
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 551
    Par défaut
    ce n'est pas parce que B hérite de A que vector<B*> est compatible avec vector<A*>, le compilateur ne peut pas le savoir, par contre vous pouvez faire tranquillement un cast pour l'aider
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  13. #13
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 61
    Par défaut
    Je dois avouer que je me suis un peu perdu là. =/ J'ai essayé diverses choses, mais je n'arrive toujours pas à faire fonctionner mon programme de la manière dont je voudrais. Actuellement, j'ai une exception non gérée au niveau de la direction (pourtant, celle-ci n'est pas nulle par défaut) mais même si je retourne une direction par défaut il m'affiche une tonne de joueurs... Peut-être est-ce là un problème lors de l'initialisation de la map des joueurs ?

    J'ai update mes sources, si jamais vous pouvez y jeter un petit coup d'oeil.

    Je ne sais pas si je suis très clair, mais j'aimerais un fonctionnement de ce type pour mon programme :

    - une classe abstraite Map contenant des fonctions de base, ainsi qu'un attribut tableau contenant la map en question
    --- plusieurs autres classes XXXMap dérivant de la classe Map ; le tableau devra changer de type pour chacune, c'est à dire que pour PlayersMap on aura un tableau PlayersMap mapTable alors pour BonusMap on aura un tableau de type BonusMap => Ce comportement semble ok avec la classe template

    - une classe abstraite Entity contenant un pointeur vers une classe Map
    --- plusieurs classes dérivant d'Entity (Players, Bomb, ...) contenant chacune un pointeur vers LEUR propre map ; c'est à dire que le pointeur déclaré en attribut dans la classe abstraite doit s'adapter : pour la classe Players, il s'agit d'un pointeur vers une PlayersMap, tandis que pour la classe Bomb il s'agit d'un pointeur vers une BombMap

    Je pensais tout bêtement définir le pointeur en temps que Map*, et croyais qu'en passant une PlayersMap à la fonction setMap(Map*) ça marcherait... Mais non, comme apparement on ne peut pas transtyper dans le sens fille->mère (ce qui paraît, somme toute, assez logique).

    Croyez-vous qu'il existe une solution propre pour arriver à mes fins ?

    Merci d'avance.

  14. #14
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 551
    Par défaut
    Citation Envoyé par NainTernaute Voir le message
    le pointeur déclaré en attribut dans la classe abstraite doit s'adapter : pour la classe Players, il s'agit d'un pointeur vers une PlayersMap, tandis que pour la classe Bomb il s'agit d'un pointeur vers une BombMap
    que voulez-vous dire par s'adapter ?
    lorsque je regarde dans les sources je vois cet attribut redéfini dans les sous classes

    Citation Envoyé par NainTernaute Voir le message
    Je pensais tout bêtement définir le pointeur en temps que Map*, et croyais qu'en passant une PlayersMap à la fonction setMap(Map*) ça marcherait... Mais non, comme apparement on ne peut pas transtyper dans le sens fille->mère (ce qui paraît, somme toute, assez logique).
    je ne comprends pas non plus ce que vous voulez dire, par contre lorsque je regarde dans les sources je vois :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class CEntity {
       ...
       virtual void setMap(CMap<CEntity*>* map);
       ...
    };
     
    class CPlayer : public CEntity {
       ...
       void setMap(CPlayersMap* map);
       ...
    };
    au cas ou penseriez le contraire, sachez que l'opération setMap définie sur CPlayer n'est pas une redéfinition de l'opération homonyme définie sur CEntity, en effet leur profile n'est pas le même (argument de type différent). Le fait que l'opération soit virtuelle au niveau de CEntity ne sert donc à rien.
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  15. #15
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 61
    Par défaut
    Arf oui, les dernières sources à jour font suite à des tests en fait ; à la base, j'aimerais justement ne pas avoir à redéfinir les attributs/méthodes.

    J'aimerais simplement pouvoir appeler la méthode setMap d'un objet Player par exemple, et que celle-ci comprenne qu'elle va recevoir une PlayersMap. De même pour l'attribut, j'aimerais ne pas devoir le redéfinir. J'aimerais que l'attribut déclarer comme CEntity* dans la classe abstraite puisse s'utiliser comme un CPlayer* dans la classe CPlayer.

    Est-ce possible ?

    EDIT : J'ai à nouveau édité mes sources. En fait, peut-être qu'une simple classe template CMap bien conçue serait utile, plutôt que plusieurs classes qui héritent d'une classe abstraite. En revanche, le système Entity et dérivés reste nécessaire. Là c'est presque bon, mais ça ne compile toujours pas à cause des différences entre Entity* et Players* ; seulement, j'ai beau mettre des dynamic_cast je n'arrive à rien. :/

  16. #16
    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,

    Une petite question idiote...

    Vu que ta CEntity dispose des informations utilisées par setPosX, setPosY, setMap, getPosX et getPosY, je présumes que le comportement de ces fonctions ne sera pas modifié dans les classes dérivées.

    Dés lors, pourquoi rendre ces fonctions virtuelles
    1. Ca risque de d'induire en erreur en te faisant penser que tu peux modifier le comportement de ces fonctions, alors qu'il n'y en a absolument pas besoin
    2. Tu paye un cout supplémentaire à chaque appel, qui pourrait parfaitement être évité
    Par contre:

    Le destructeur de CEntity devrait être virtuel, car il y a de fortes chances que tu veuilles utiliser les différents entité comme des... pointeurs sur CEntity, et que tu veuille appeler delete sur ces pointeurs.
    getPosX et getPosY devraient être des fonctions constantes, bien plus que renvoyer des ... const int (même s'il n'est pas faux de renvoyer des const int )
    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

  17. #17
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 61
    Par défaut
    En effet, j'ai réfléchi un peu à tout ça hier soir, et me suis rendu compte que j'avais "mal compris" l'intérêt et le fonctionnement des méthodes virtuelles. Celles-ci sont prévues pour être redéfinies dans les classes filles, ce qui permet ensuite au compilateur d'apeller la bonne méthode suivant l'objet utilisé, n'est-ce pas ?

    Par exemple, si je fais ça :

    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
     
    class A {
      public:
        virtual void fonction(); // Comportement de base
    };
     
    class B : public A {
      public:
        void fonction(); // Comportement spécifique
    };
     
    void maFonction(A object) {
      object.fonction();
    }
     
    B objectB;
    maFonction(B);
    Alors le code doit marcher et appeller la méthode "fonction()" définie dans la classe B, n'est-ce pas ?

    Ce qui du coup rend en effet mes getters/setters inutiles en "virtual".

    En ce qui concerne le type de retour const et la fonction const, je dois avouer que je m'étais un peu mélangé (ou du moins n'y avait pas prété beaucoup d'attention). Merci d'avoir pointé ce problème.

  18. #18
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Alors le code doit marcher et appeller la méthode "fonction()" définie dans la classe B, n'est-ce pas ?
    Non, il faut passer l'objet par référence ou pointeur, pas par copie.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  19. #19
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 61
    Par défaut
    Ah d'accord. J'ai finalement résolu mon problème de base, en modifiant également la classe CEntity afin que celle-ci devienne une class template :

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    #ifndef _CENTITY_
    #define _CENTITY_
     
    template<typename T> class CMap;
     
    /*
    	Abstract class CEntity
    	Defines elements that can be herited by all entities (players, bombs, bonus)
    */
     
    template<typename EntityType> 
    class CEntity {
     
    	protected:
    		int m_posX;
    		int m_posY;
    		CMap<EntityType*>* m_pMap;
     
    	public:
    		int getPosX() const;
    		int getPosY() const;
    		void setPosX(const int x);
    		void setPosY(const int y);
    		void setMap(CMap<EntityType*>* map);
     
    };
     
    /*
    	void setMap(CMap* map)
    	Link entity and his map with a pointer
    */
    template<typename EntityType>  void CEntity<EntityType>::setMap(CMap<EntityType*>* map) {
    	m_pMap = map;
    }
     
    /*
    	Getters & setters
    */
     
    template<typename EntityType>  int CEntity<EntityType>::getPosX() const {
    	return m_posX;
    }
     
    template<typename EntityType>  int CEntity<EntityType>::getPosY() const {
    	return m_posY;
    }
     
    template<typename EntityType>  void CEntity<EntityType>::setPosX(const int x) {
    	m_posX = x;
    }
     
    template<typename EntityType>  void CEntity<EntityType>::setPosY(const int y) {
    	m_posY = y;
    }
     
    #endif
    En revanche, un problème subsiste : si jamais la case est vide, j'aimerais qu'elle contienne un pointeur nul (ou tout autre valeur qui me permettrait de dire que la case est vide). J'ai essayé en lui passant "NULL" mais ça bug à l'execution sur cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template<typename TableType> void CMap<TableType>::setCaseState(int x, int y, TableType state) {
    	m_mapTable[y][x] = state;
    }
    Quand "state" est NULL, j'ai cette erreur lors de l'exécution :

    Une exception non gérée du type 'System.NullReferenceException' s'est produite dans Bomber.exe
    Je pense comprendre que ça vient justement du fait qu'on pointe vers rien, mais comment faire alors ? TableType est bien ici CPlayer*, ce qui devrait autoriser la valeur NULL non ?

    Merci d'avance

    EDIT : le problème ne semble en fait pas venir du passage d'un NULL, mais du passage de "this" ; pourtant, ça devrait fonctionner non ? Les sources sont updates, si vous pouviez jeter un coup d'oeil svp. Je nage là =/

  20. #20
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 551
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 551
    Par défaut
    le problème ne semble en fait pas venir du passage d'un NULL, mais du passage de "this"
    cela veut à priori dire que this est null, vous ne pouvez pas voir pourquoi via un debugger ?
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Passage tableau string en parametre par pointeur
    Par andrebernard dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 12/03/2011, 11h10
  2. Réponses: 2
    Dernier message: 23/03/2010, 21h40
  3. Transformation d'un String en tableau 2D de int
    Par demonixis dans le forum Collection et Stream
    Réponses: 4
    Dernier message: 11/04/2009, 11h51
  4. Réponses: 11
    Dernier message: 14/10/2006, 21h26
  5. Réponses: 3
    Dernier message: 27/08/2006, 14h25

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