Au vu de toute ces explications tout se précise surtout sur la cas de la flemmardiseje me douter de la signification. merci pour cette longue et très précise réponse
Au vu de toute ces explications tout se précise surtout sur la cas de la flemmardiseje me douter de la signification. merci pour cette longue et très précise réponse
Une précision concernant size_t (qui ne concerne pas cette discussion, mais qui me semble importante). En plus de ce qui a déjà été dit, size_t résous certains problèmes dus au fait que la taille réelle des types natifs en c++ ne sont pas définis par le standard. En gros, lorsqu'on utilise size_t, on laisse la responsabilité à la SL des choix concernant la taille réelle (voire même l'encodade, si j'ai bien compris, sur certaines plateformes exotiques); ainsi on améliore la portabilité de notre code et on se simplifie la vie. Cette précision concerne les plateformes "inhabituelles", en particulier les devices destinés à l'embarqué.
En fait, il y a aussi l'aspect de l'inlining de la fonction qui n'est pas à négliger, surtout pour des fonctions très simples (comprends: des fonctions qui seront "traduites" par un nombre très bas d'instructions processeur).
Il faut savoir que, chaque fois que tu fais appel à une fonction non inline, il y a une séries d'instructions processeur qui fait en sorte de préparer l'appel à la fonction avant qu'elle ne soit appelée et de préparer le retour au "bon endroit du code" lorsque la fonction est terminée.
Ces instructions sont présentes et en nombre constant, bon an mal an, pour tout appel de fonction qui sera effectué.
Bien sur, cela ne correspond qu'à un très petit nombre de cycles d'horloge pour le processeur et donc à un délais particulièrement minime, mais il reste dommage de "perdre" ces cycles à attendre que le programme prépare l'appel et la sortie de la fonction quand on sait pertinemment que le corps de la fonction elle-même prendra un nombre de cycles d'horloge plus faible que le total de ces "préface" et "postface", surtout si c'est une fonction qui est destinée à être appelée en de très nombreuses occasion (parfois plusieurs dizaine de milliers de fois !!) par exemple.
En décidant judicieusement d'inliner certaines fonctions, on peut arriver à constater un gain non négligeable en terme de performances
On peut presque considérer comme une pratique courante le fait d'inliner des fonctions comme:mais l'opportunité de ce faire doit malgré tout être évaluée à chaque fois
- des accesseurs
- les opérateurs de comparaison
- certains opérateurs "mathématiques" (pour autant qu'il ne nécessitent pas forcément de copie de leurs paramètres)
- ...d'autres exemples pourraient me venir en tete plus tard
![]()
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
euh petite autre![]()
les & entre const et filename ou SMap et map veulent dire la meme chose que si on faisait sa ou pas
Code : Sélectionner tout - Visualiser dans une fenêtre à part void loadMap(SMap & map, std::string const & filename)
si non pourriez m'expliquer qu'est ce que cela change
Code : Sélectionner tout - Visualiser dans une fenêtre à part void loadMap(SMap map, std::string const filename)
Attention, si une référence const est fonctionnellement équivalente (par manque d'un meilleur mot) à un passage par copie, ce n'est pas du tout le cas d'une référence non-const! Celle-ci permet à la fonction de modifier l'objet passé en paramètre...
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.
alors encore des question
1ere question :
n'est t'il ps dangereux d'avoir 2 fonction qui porte le meme nom comme dans l'exemple suivant
2eme question :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 /* et, comme on peut travailler en orienté objets, on peut rajouter * une fonction membre qui renvoie le caractère qui se trouve en X,Y ;) */ const unsigned char tileAt(size_t x, size_t y) const {return tiles_[y*cols + x];} /* et la même chose avec une Position (sait on jamais ;)) */ const unsigned char tileAt(Position const & pos) {return tileAt(pos.x(), pos.y());}
serais ce possible d'avoir une explication de ce bout de code car il sont appeler null part donc je n'est pas trouver leur utiliter
3eme question :
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 /* Pour pouvoir utiliser la std::map, on a besoin de l'opérateur de *comparaison < * */ bool oprtator <(Position const & first, Position const & second) { return first.x() < second.x() || (first.x() == second.x() && first.y() < second.y() ); } /* et, tant qu'à faire, te l'opérateur de comparaison == (pour d'autres * usages ultérieurs, très certainement ;) */ bool oprtator ==(Position const & first, Position const & second) { return first.x() == second.x() && first.y() == second.y() ); }
le toFill du code suivant est de quel type et sert a quoi exactement ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 void loadMapList(std::map<Position, std::string> & toFill) { std::ifstream ifs("world.txt"); int x; int y; std::string filename; while(ifs>>x>>y>>filename) { toFill.insert(std::make_pair(Position(x,y),filename); } }
- Aucun problème en C++, la surcharge c'est fait pour ça. Par contre, il n'est pas normal que la seconde méthode ne soit pas const.
- Note déjà qu'il y a une typo dans le mot-clé operator. Ensuite, c'est la méthode traditionnelle en C++ pour les comparaisons de type perso: On redéfinit operator<, qui retourne un Booléen (true si le premier objet est strictement inférieur au second). Tu ne le vois appelé nulle part, mais std::map en fait un usage intensif (c'est un conteneur trié, ne l'oublie pas).
- Pour l'opérateur d'égalité, c'est à peu près la même chose.
- toFill est une référence non-const vers une std::map de Position vers string: La fonction loadMapList() va remplir cette std::map avec les données lues dans le fichier world.txt, qui indique pour chaque couple de coordonnées le nom du fichier texte contenant les infos de la map correspondante.
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.
Mais ici cette ligne le insert il veut dire quoi parce que à première vue et suite à des recherches je sais que il y a std::insert mais la c'est insert tout court donc cela voudrai dire que c'est une fonction ou procédure et n’étant déclaré nul part je présume que c'est lier à une classe donc pouvais m'en dire plus ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part toFill.insert(std::make_pair(Position(x,y),filename);
Là, tu en oublies jusqu'aux bases de la programmation objet: Il s'agit ici de la méthode std::map<keytype, valuetype>::insert!
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.
Ah d'accord non je n'oublie pas mais je n'avais pas vue les méthodes que contiennait map du coup je ne faisais pas le lien merci
C'est "presque" la même chose:
Simplement, la première version (celle qui contient les &) va transmettre map sous la forme d'une référence et filename sous la forme d'une référence constante alors que la deuxième version (celle qui ne contient pas les &) va transmettre les arguments par valeur, et donc par copie.
Comme on souhaite explicitement que les modifications apportée à map dans loadMap soient répercutées sur la variable maplist dans la fonction principale, il faut à tout prix faire en sorte que map ne soit pas une copie, mais bel et bien un alias de la variable d'origine
Non, il n'y a strictement aucun problème.
Tout ce qu'il faut, pour pouvoir profiter de la surcharge de fonctions, c'est une différence dans le nombre ou dans le type des paramètres attendus.
Tu auras d'ailleurs remarqué que l'implémentation de la deuxième version (celle qui prend une référence constante sur un objet de type Position) ne fait qu'appeler la première version (celle qui prend une valeur X et une valeur Y).
Et c'est voulu: le nom d'une fonction reflète le service que tu attends qu'elle te rende.
Le service que tu attends de la fonction tileAt est... de t'indiquer la tuile qui se trouve à une position donnée.
Que la position soit de transmise sous la forme d'une valeur pour x et d'une valeur pour y ou sous la forme d'un objet de type position ne change strictement rien, du moment que tileAt(5,10) et tileAt(Position(5,10)) renvoient bel et bien la même tuile
L'idée est "simplement" de fournir un comportement qui renvoie la tuile qui se trouve à la position donnée, que tu disposes de l'abscisse et de l'ordonnée ou d'un objet de type Position car tu ne sais, a priori, pas si l'utilisateur préférera travailler avec une version ou avec l'autre
Et c'est tout à fait légal en C++
Il y a, effectivement une erreur de typo, car ca devrait etre2eme question :
serais ce possible d'avoir une explication de ce bout de code car il sont appeler null part donc je n'est pas trouver leur utiliter
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 /* Pour pouvoir utiliser la std::map, on a besoin de l'opérateur de *comparaison < * */ bool oprtator <(Position const & first, Position const & second) { return first.x() < second.x() || (first.x() == second.x() && first.y() < second.y() ); } /* et, tant qu'à faire, te l'opérateur de comparaison == (pour d'autres * usages ultérieurs, très certainement ;) */ bool oprtator ==(Position const & first, Position const & second) { return first.x() == second.x() && first.y() == second.y() ); }
(faut vraiment que j'arrête de poster passé une certaine heure
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 /* Pour pouvoir utiliser la std::map, on a besoin de l'opérateur de *comparaison < * */ bool operator <(Position const & first, Position const & second) { return first.x() < second.x() || (first.x() == second.x() && first.y() < second.y() ); } /* et, tant qu'à faire, te l'opérateur de comparaison == (pour d'autres * usages ultérieurs, très certainement ;) */ bool operator ==(Position const & first, Position const & second) { return first.x() == second.x() && first.y() == second.y() ); }![]()
)
Ce ne sont que des opérateur de comparaison (les mêmes que tu pourrais utiliser pour des codes comme if (i <5) ou if (j == 43) mais adaptés pour le type Position
La classe std::map fait un usage intensif de l'opérateur < (plus petit que) pour tout ce qui a trait au tri, et l'opérateur ==, ben on risque d'avoir à l'utiliser de manière régulière à d'autres moments
As tu vu l'image que j'ai postée dans ma première intervention3eme question :
le toFill du code suivant est de quel type et sert a quoi exactement ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 void loadMapList(std::map<Position, std::string> & toFill) { std::ifstream ifs("world.txt"); int x; int y; std::string filename; while(ifs>>x>>y>>filename) { toFill.insert(std::make_pair(Position(x,y),filename); } }
Tu auras remarqué que j'ai donné un exemple de "monde" dans lequel tes différentes cartes pourraient s'inscrire.
J'ai, pour chaque carte qui s'inscrit dans se monde, choisi une couleur, une largeur et une hauteur.
j'ai aussi indiqué les coordonnées auxquelles se trouve leur coin supérieur gauche.
Cette fonction permet de lire le fichier "world.txt" qui contient l'ensemble des cartes qui existent dans le monde et de remplir le tableau associatif qui met un nom de fichier en relation avec les coordonnées auxquelles se trouve le coin supérieur gauche de la carte en question.
Lorsque tu veux changer de carte (que ce soit en passant par une porte ou par un télé-porteur), les informations contenues dans la structure SWrap te permettent de déterminer la position du coin supérieur gauche de la carte vers laquelle tu veux te déplacer.
Grâce au conteneur associatif que la fonction aura rempli, tu pourra facilement trouver le nom du fichier qui contient les information relatives à cette carte.
Et, grâce à ce nom de fichier, tu pourras charger le dit fichier afin d'obtenir la carte en question
toFill est le nom d'une variable de type std::map.
Il se fait que la classe std::map (qui est, comme je l'ai dit plus haut, un tableau associatif associant une clé à une valeur) propose, car cela fait partie d'un des services que l'on est en droit d'attendre de sa part, une fonction insert.
Ce code fait "simplement" appel à la la fonction membre "insert" de la classe std::map.
Tu trouveras plein d'informations utiles sur la std::map ==>ici<==![]()
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
Merci pour ta réponse qui regroupe plusieurs questions comme à ton habitude tu m'éclaires plus surtout sur le fait d'avoir des fonctions de même nom ça je ne savais pas c'est une grande nouvelle pour moi pas très original dans le nom de mes fonctions merci encore j'espère que je n'aurais pas d'autre question bien que je sais que si car une ligne me bloque encore mais je vais pour l'instant laisser les gens se reposer parce que je pose beaucoup de questions![]()
En fait, ce n'est pas mon habitude, mais comme je suis pour le moins fort occupé pour l'instant, je n'ai malheureusement pas forcément l'occasion de répondre "just in time" (ni même de lire toutes les réponses au moment où elles arrivent).
Du coup, ben, faut bien apporter une réponse à chaque question, et j'essaye de le faire correctement![]()
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
Non mais il n'y a pas de soucis c'est parfait comme sa car en général les question on toujours quelque point de ressemblance donc voila sa apporte beaucoup d'un coup .
par contre encore une question ici nous avons cette ligne
puis celle la
Code : Sélectionner tout - Visualiser dans une fenêtre à part auto it= maplist.find(Position(0,0));
donc voila la question est la suivante it.second qu'est ce second car a première c'est pas une méthode donc je vois pas j'ai chercher il ne vient pas de std::map et j'ai rechercher avec auto rien non plus donc qu'est ce que c'est ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part loadMap(map, it.second);
En fait, ce code utilise une des nouvelles possibilités offertes par C++11.
Cela permet de faciliter l'écriture du code, mais il est vrai que, lorsque l'on ne comprend pas, ca ne facilite pas forcément la compréhension
Cette possibilité permet au compilateur de déterminer lui-même le type de l'objet en question (it dans le cas présent) et devrait être remplacé dans un code "pré C++11" par quelque chose du genre de
Cela t'aurait sans doute permis de comprendre que l'on obtenait un... itérateur (constant) sur les éléments de la map.
Code : Sélectionner tout - Visualiser dans une fenêtre à part std::map<Postion, std::string>::const_iterator it = maplist.find(Position(0,0));
Un itérateur n'est, pour faire simple, qu'une abstraction qui permet de parcourir l'ensemble des éléments d'une collection sans avoir à se poser *trop* de question
Le fait est que tous les éléments d'une map sont composés de deux choses : une clé, qui sert pour le tri, et une valeur qui correspond à la valeur "utilisable".puis celle la
donc voila la question est la suivante it.second qu'est ce second car a premiere c'est pas une methode donc je vois pas j'ai chercher il ne vient pas de std::map et j'ai rechercher avec auto rien non plus donc qu'est ce que c'est ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part loadMap(map, it.second);
Cette association entre clé et valeur est représentée par une autre abstraction nommée std:: pair (car c'est... une paire composée d'une clé et d'une valeur).
L'itérateur que l'on récupère donc en invoquant la fonction membre find de la classe std::map représente donc, tout simplement, un objet de type std ::pair (c'est la raison pour laquelle l'insertion se fait en utilisant ce qui est renvoyé par make_pair).
le type std:: pair, finalement, très simple: c'est une bête structure contenant deux données : first, qui sera du type attendu pour la clé et second qui sera du type attendu pour la donnée (car std::pair peut être utilisé à d'autres endroits sans forcément être une association "clé valeur", mais en n'étant ni plus ni moins qu'une association "première valeur, deuxième valeur")
Bon, c'est une structure template (pour laquelle on ne sait pas à l'avance quels seront les types réellement utilisés) mais, adaptée à mon exemple ressemble à quelque chose comme
Si tu veux récupérer la position, tu peux utiliser un code proche de
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 namespace std { struct pair { Position first; string second; }; }
et si tu veux récupérer la chaine de caractères qui représente le nom du fichier à charger, tu peux la récupérer à l'aide d'un code proche de
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2/* soit std::pair<Position, std::string unObjet = std::make_pair(Position(0,0),"gris.txt"); */ Position pos =unObjet.first;
Tu trouveras plus d'informations sur std:: pair ==>ici<==
Code : Sélectionner tout - Visualiser dans une fenêtre à part std::string filename = unObjet.second;
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
C'est strictement équivalent à:
auto demande au compilo de trouver le type tous seul (en général utilisé pour les itérators, comme ici, car c'est long à écrire).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 std::map<Position, std::string>::const_iterator it= maplist.find(Position(0,0)); loadMap(map, it.second);
l'iterator ici représente un std::pair<Position, std::string> et fonctionne "comme un pointeur".
tu peux le déréférencer pour accéder à l'élément qu'il représente.
Une pair possède 2 attributs public first et second (qui sont la clef (Position) et la valeur (std::string) ici).
Il y a par contre une typo, il faut bien déréférencer l'itérator.
edit: bouh, trop rapide le mangeur d'eucalyptus
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 loadMap(map, it->second); // ou loadMap(map, (*it).second);![]()
Encore une fois explication excellente rien à dire. Ah si seule chose c'est que j’avais quand même fait le rapprochement entre it et iterator mais après pour le reste je n'aurais certainement pas trouvé et pas aussi bien expliqué merci à toi maintenant que j'ai compris je vais pouvoir enfin toucher à tout ça en connaissance de ce que je fais.
Par contre la classe position peut être utilisée pour le déplacement tu joueur aussi ou tu penses que je devrais la laisser pour map ?
C'est tout l'avantage de choisir des noms "explicites" (bien que j'aurais sans doute pu choisir plus clair encore)
Mais si, une fois qu'on connait quelque chose, il suffit d'appliquer la citation de ma signaturemais aprés pour le reste je n'aurais certainement pas trouver et pas aussi bien expliquer
Avec plaisirmerci a toi maintenant que j'ai compris je vais pouvoir enfin toucher a tout sa en connaissance de se que je fais.
Hé bien, je ne vais pas répondre à cette question (il faut bien que tu cherches un tout petit peu nonparcontre la class position peu etre utiliser pour le deplacement tu joueur aussi ou tu pense que je devrai la laisser pour map)...
Mais je vais néanmoins te mettre sur la voie en te disant que le role de la classe Position est de représenter un couple de valeurs en abscisse et en ordonnée sur base d'un référentiel donné (que ce soit la carte du monde ou la carte du niveau).
Qu'en déduirais tuSelon toi, où auras tu besoin d'un tel couple de valeurs
![]()
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
J'en déduirai que étant juste un couple de valeurs il sont tout à fait apte à être utilisé comme coordonnées donc le déplacement se faisant à l'aide de coordonnées ceci convient totalement
Hehe, penses tout de même à faire un typedef pour savoir que cela représente un déplacement et non une position.
Partager